Keybow 2040 Anyone figure out UTF/Unicode support?

Title pretty much says it all, ran through the adafuit_hid documentation, but apparently only codes from a standard keyboard work, and not any extended codes.

is there a way to force {alt+####} sends?

For reference, the characters I’m aiming for are well outside even high ascii (lots of math related symbols)

any help appreciated

You should head over to GitHub - Neradoc/Circuitpython_Keyboard_Layouts: A repository of keyboard layouts for Circuitpython, for HID keyboards over USB or BLE.. There you will find keyboard-layouts for various languages. More interesting for your case might be the Readme (scroll down), that describes how to use the command-keys (like alt).

1 Like

Unfortunately the alternate keyboard layouts are not applicable to my use case (unicode symbols, vs language pages) as I’m unaware of any keyboard mappings that would contain more than a few. AFAICT flipping language pages would also require a reset for the OS to pick up the new language reference.
I’m sure it will help someone needing native language support, but doesn’t appear to be doable for arbitrary unicode.

I did find the section in the Adafruit_CircuitPython_HID repository you mentioned on control codes, (which I initially misread as only allowing single characters), It’s… clunky to say the least, requiring a lot of manual lookups, and a I’ll have to write a much more complex handler for it, so I’m reserving that option for later if no one else chimes in with other options.

As a follow up question,
Are you (or anyone reading) aware of a method that would let me programmatically write to the clipboard from the keybow, then trigger a paste? seems a longshot for an HID device but no harm asking. At first I thought that’s what adafruit library did with the write function, but in reality it just references the language layout then spits out the keycodes in rapid sequence… and chokes on anything unrecognized.

As HID is just a keyboard, it can do anything that a normal keyboard can do. On Windows for example, if your keyboard-input is within a PowerShell, you can type and use PowerShell functions for that. On Linux, you would use xsel. I think Mac has something named pbcopy/pbpaste. These are all just commands, and your keybow has to type them in.

I don’t quite get that. You asked for sending alt+####, so this line should do it:

kbd.press(Keycode.ALT, Keycode.ONE, Keycode.TWO,Keycode.THREE,Keycode.FOUR)

This will send ALT+1234

Also requires a release for all those as well… and I’m not sure you can send multiple characters (as opposed to modifiers) in a single call like that, but I’d have to double check… but that wasn’t what I meant by more complex handler.

Your example handles a single unicode character, I’m currently doing 8 (soon to be more) pages/layers of 15 macros (120 effective buttons), and not all of those are single characters. so I’m going to need to either parse each character in each button entry of each page/layer, with a lookup, or write a more complex container for each button. and of course each of those unicode characters has to be looked up and written out in the correct format.

enabling windows unicode hex entry, I think I can get away with this slightly less clunky construct

keyboard.press(  Keycode.ALT, Keycode.KEYPAD_PLUS )
layout.write( "221D" )
keyboard.release_all()

and if so, I’ll probably take a combination approach, parsing each button entry element depending on whether it’s array or text and, encode each button entry as something like

{"ascii ",{MODIFIER_FLAG, UNICODE_POINT}, " more ascii" }

not quite user friendly, so I doubt it’ll get much use when I share it, but barring anyone being aware of other alternatives it looks like that’s what I’ll need to do. I’ll leave this here for a week or two and if no better alternative is posted I’ll flag yours as the solution with my thanks for your assistance.

ETA:
Re: “anything a keyboard can do”, for clipboard access I was more thinking of USB functions outside of the HID library… but I wrote that poorly. Sometimes my brain skips a few steps ahead of my writing, mea culpa.

I was more wondering if (given that keybow presents as an HID device) if some other presentation had direct write access to the clipboard, and if it could be shoehorned in. My understanding is “no”, but hardware coding is a new hobby for me, so I’m not aware of all the options/limitations.

Correct. Your program runs on the MCU, the clipboard runs within the OS of your PC. Two distinct worlds.

What you could do is add a helper program on the PC and then your MCU can communicate e.g. with UART with this helper-program.

= S

so I got to testing, both of the following fail spectacularly…

# original suggestion [decimal unicode for pi]
keyboard.send( Keycode.ALT, Keycode.KEYPAD_TWO, Keycode.KEYPAD_TWO, Keycode.KEYPAD_SEVEN )
# expected --> π
# actual --> '

# My proposal (with windows unnicode hex entry enabled) [hex unicode for small a acute]
keyboard.press( Keycode.ALT, Keycode.KEYPAD_PLUS )
layout.write( "227" ) 
keyboard.release_all()
# expected --> ȧ
# actual --> 27
# keyboard.send instead of layout.write fails here too differently

Why? I dug into the Adafruit HID source docs and found that .send() is just implemented as a series of .press() commands (which obliterates any repeated characters), and .write() is implemented with .release_all() after every character (obliterating the required held alt key)

So what does work? When all else fails, be painfully explicit…

keyboard.press( Keycode.ALT )
keyboard.press( Keycode.KEYPAD_TWO )
keyboard.release( Keycode.KEYPAD_TWO )
keyboard.press( Keycode.KEYPAD_TWO )
keyboard.release( Keycode.KEYPAD_TWO )
keyboard.press( Keycode.KEYPAD_SEVEN )
keyboard.release( Keycode.KEYPAD_SEVEN )
keyboard.release( Keycode.ALT ) 
# or alternately with windows unicode hex  entry enabled
keyboard.press( Keycode.ALT )
keyboard.press( Keycode.KEYPAD_PLUS )
keyboard.release( Keycode.KEYPAD_PLUS )
keyboard.press( Keycode.TWO )
keyboard.release( Keycode.TWO )
keyboard.press( Keycode.TWO )
keyboard.release( Keycode.TWO )
keyboard.press( Keycode.SEVEN )
keyboard.release( Keycode.SEVEN )
keyboard.release( Keycode.ALT ) 

Not exactly pretty, but I can write a handler to make entering macros easier. I’ll try to remember to post that back here.

I’ll be suggesting a change to .write to use .release() instead of .release_all(), but even if included that will only help those with windows unicode hex entry enabled. Changes to the handling of .send() are also going to be suggested (but may be more difficult since I haven’t looked at how easy it is flag modifiers vs keys).

If I get spare time I’ll write a generalized “macro input” so that macros can be written the same way you would on a commercial programmable keyboard or mouse, and just spit out to a dictionary you can save back to the keybow. No one hold their breath… holidays are busy times and I’m easily distracted.

My thanks to @bablokb for setting me on the path

As promised, a macro handler to make macros a bit easier (and a bit more flexible) to enter

it’s not more commercial style one, but it a base to which it can be added later

2 Likes