pimoroni / keybow-firmware Goto Github PK
View Code? Open in Web Editor NEWKeybow Firmware for the Raspberry Pi Zero
License: Other
Keybow Firmware for the Raspberry Pi Zero
License: Other
As I simply could not find any documentation on this, I'm misusing GItHub issues to ask this question and also suggest documenting this:
https://github.com/pimoroni/keybow-firmware/blob/master/keybow/lights.c#L108
What's that magic number? Why not 255 instead of 227? 255 seems to do the job as well. And what's that field in first place? I first thought it's the brightness, however, while it does seem to make the LEDs brighter when running at 255 instead of 227, it does not seem to support all numbers.
Could you please give some insights on this?
Is there a means besides the standard caps lock, etc. LED control to tell a Keybow USB device which keyboard (layout) state it should be in? E.g., to switch into a "debugging keyboard layout" while my IDE is in program debug mode?
I've been trying to use the serial support added at v0.0.4 to change the key mapping with something like the following:
require "keybow"
-- Keybow MINI volume/zoom controls --
function setup()
keybow.use_mini()
keybow.auto_lights(false)
keybow.clear_lights()
keybow.set_pixel(0, 0, 255, 255)
keybow.set_pixel(1, 255, 0, 255)
keybow.set_pixel(2, 0, 255, 255)
end
-- Key mappings --
state = 'zoom'
function handle_minikey_02(pressed)
if state == 'zoom' then
if pressed then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key("v")
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
end
elseif state == 'media' then
keybow.set_media_key(keybow.MEDIA_VOL_UP, pressed)
end
end
function handle_minikey_01(pressed)
if state == 'zoom' then
if pressed then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key("a")
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
end
elseif state == 'media' then
keybow.set_media_key(keybow.MEDIA_MUTE, pressed)
end
end
function handle_minikey_00(pressed)
if state == 'zoom' then
if pressed then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key("n")
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
end
elseif state == 'media' then
keybow.set_media_key(keybow.MEDIA_VOL_DOWN, pressed)
end
end
local function isempty(s)
return s == nil or s == ''
end
function tick()
local line
line = keybow_serial_read()
if not isempty(line) then
-- keybow_serial_write( line .. "\n" )
if line == 'zoom' then
keybow.clear_lights()
keybow.set_pixel(0, 0, 255, 255)
keybow.set_pixel(1, 255, 0, 255)
keybow.set_pixel(2, 0, 255, 255)
state = 'zoom'
elseif line == 'media' then
keybow.clear_lights()
keybow.set_pixel(0, 255, 0, 255)
keybow.set_pixel(1, 0, 255, 255)
keybow.set_pixel(2, 255, 0, 255)
state = 'media'
end
end
end
It's really laggy which I think is down to:
keybow-firmware/keybow/serial.c
Line 37 in ec9bc99
Which sets a 1 second read timeout on the serial connection.
I tried reducing that to 1 decasecond but when I built the keybow
binary (on a different pi zero) from the head of the repo it doesn't look to setup the USB gadget properly (at least it never shows up on the host machine).
Any suggestions?
Or suggestions on how to debug, I attached a screen, but it just drops me at a login prompt and there is no way to add a keyboard as the USB port is in device mode to talk to the host. (When Pi Zero W's become available again I will try and grab one so I can ssh in and have a look).
P.s. I understand the world has probably mainly moved on to the 2040 based kit, but this is still useful and being able to switch profiles would be huge upgrade.
trying to input date by pressing key, but im getting year 2016 somehow.
how to fix it?
keybow.text(os.date ("%Y-%m-%d"))
Because keyboard interface is not specifying the keyboard mapping, Keybow/LUA software seems to assume you use QWERTY in UK or US (to be verified) setting.
With my MAC configured for AZERTY Belgian FR, I get "strange" result.
So if I say that a key should send an "m" it will send a ","
If I use the following to produce a "qwaz" by pressing key 00, I get a "azqw":
function handle_key_00(pressed) -- Lorem Ipsum
if pressed then
keybow.text([[
qwaz
]])
So the "Lorem ipsum dolor..." does not look the same anymore.
What is needed is some kind of "reverse mapping" (a set of reverse mapping to choose from) that can be applied to everything you request. The default mapping would be "no mapping" and work for UK or US keyboard. That way, any working script can be just modified for your specific mapping.
PS: I don't have a keybow hardware, I just tested the software with a ZeroSeg that has two button, one that is "key_00".
See here for details and the "fixed" set_key
method: https://forums.pimoroni.com/t/keybow-running-a-desktop-shortcut/10140
Need to find a better, user-configurable way of emitting the right keycodes for the right regions- the fix mentioned in the forums currently uses hard-coded edge cases to account for # ~ | \
.
Moving the shift key release until after the key release is a minor bugfix to avoid weird casing issues when outputting text.
Be handy to have official schematics for Keybow.
To include LED numbering, key GPIO assignments, etc.
The provided keys.lua, there is a reference to the pattern "test-4x3" but there is not file "test-4x3.png" in the repository:
function handle_key_00 (pressed)
keybow.set_key("0", pressed)
keybow.load_pattern("test-4x3")
end
I'm interested in extending the MIDI function, enabling the Keybow to send all kind of MIDI messages besides the NoteOn/NoteOff.
I'm not a C programmer at all, so my attached example code could be totally unadequate: take it only as an example of how I'd like to see it working.
void sendMIDImessage(int channel, int code, int b1, int b2, int b3) {
unsigned char buf[4];
buf[0] = code | channel & 0x7f;
buf[1] = b1 & 0x7f;
buf[2] = b2 & 0x7f;
buf[3] = b3 & 0x7f;
write(midi_output, buf, 4);
}
void sendMIDINote(int channel, int note, int velocity, int state) {
unsigned char code
if(state==1){
code = 0x90;
}
else
{
code = 0x80;
}
sendMIDImessage(channel, code, note, velocity, 0);
}
Tried to assign the left side of the keyboard near WASD including left shift and left ctrl, did not work. Was not registered by reading all inputs either Issue was fixed by changing the keybow lua file to assign those keys to their HID usage keycodes (0xE0 to 0xE7). I also commented out the section later which uses those keys, not sure if that will cause issues.
Hi there, i just recently bought my Keybow and i was wondering if it is possible to emulate mouse movement via Keybow. The Device is recognized as a Generic HID and there a keyboards with embedded trackpads. I would like to emulate Mouse Movement via pressing a Button (Like Cursor Keys on the Keyboard but for the Mouse Pointer), This could be achieved by requiring the windows api ("winapi by Steve Donovan") or something similar. I tried this by adding the library to the SD Card and requiring it in the custom layout but i get no Feedback (as in Debug Information or LUA Errors). It seems that the Operations fail.
I don't know if this Project is maintained anymore. But any help would be greatly appreciated.
hi,
is it possible to interrupt the colour pattern for a manual colour when the key is pressed. when released the colour pattern continues?
i've attempted to turn off auto_lights, adjust the colour then turn them back on, by loading the default.png back in. but to no avail.
require "keybow"
-- Keybow MINI --
function setup()
keybow.use_mini()
--keybow.auto_lights(False)
--keybow.clear_lights()
end
-- Key mappings --
function handle_minikey_00(pressed)
if pressed then
keybow.set_key("0", pressed)
keybow.auto_lights(False)
keybow.set_pixel(0, 0, 255, 0)
keybow.set_pixel(1, 255, 0, 0)
keybow.set_pixel(2, 255, 0, 0)
keybow.auto_lights(True)
load_new_pattern()
else
keybow.set_pixel(0, 0, 255, 0)
end
end
function load_new_pattern()
keybow.load_pattern('default')
end
I have tried to use the following to create a special key combination which is just CAPSLOCK & F12 (for use with Autohotkey) but the keybow doesn't appear to be sending CAPSLOCK, any chance you can make CAPSLOCK a modifier if it isn't already?
keybow.set_modifier(keybow.CAPSLOCK, keybow.KEY_DOWN)
keybow.tap_key(keybow.F12)
keybow.set_modifier(keybow.CAPSLOCK, keybow.KEY_DOWN)
hi, when i try and run this on my 3B with a PoE HAT it only gets to the rainbow screen with the undervoltage sign (latest full raspbian doesn't have this issue)
The Makefile works great for building the application, but how was the initrd/initramfs created?
Any hint on the script/command used to rebuild it so that we can debug / modify things easier?
thanks!
I downloaded the files at https://github.com/pimoroni/keybow-firmware and wrote the 'sdcard' directory to an SD card.
On booting the Pi Zero, the keybow service doesn't start. There is no /usr/bin/keybow file though the keybow.service systemd unit file is there, and trying to start /usr/bin/keybow. When I manually copied in the keybow binary, it complains that it can't find the keys.lua file.
I manually mounted /dev/mmc0blk0 under /boot, created a /boot/user directory and then copied the keys.lua file in there - then it worked. Unfortunately, manually hacking that into the initrd didn't work for me...somehow the EUID of root was 1001. This can only be built on a Debian system, yes ?
Documentation request.
I think the exact instructions to reducing the buster/raspbian 10 image for your 2020nov keybow firmware would be helpful. Maybe as simple as the transscript/history from the image creation.
AFAIS the github repo describing a generic pimoroni process for distro reduction seems to be configurable, and to start, I'd prefered something similar to your wifi firmware with as little
changes as possible, just being able to use nfs/ext2/ext4 and an editor command would
have been plenty.
When creating my workaround-firmware-overlay tree (see other issue to be created in a minutes), I was struggling to repack the initrd. Having the transcript and the exact command would have saved me an hour.
(... | cpio -o -H newc | xz -9fc --check=crc32 --lzma2=dict=512KiB did rebuild the initrd and finally worked with the kernel from the above mentioned firmware image)
Thx
Peter
I have keybow mini. I use it with Window 10 and connect via OTG. When the computer starts, keybow starts as well. After the start-up period, the keybow have fixed colours on keys - not changing. It doesn't work when pressing keys.
When I unplug and immediately plugin keybow, it works fine. I also realised that if I don't use keybow for a couple of hours, I have to again unplug it and plugin back to start working.
The blog post linked in #38 makes a good point that our documentation lacks any explanation for how the pixels in PNG animations map to the LEDs on the keybow. We should fix this.
running keybow-0.0.4 -
Changed keys.lua to require the layouts/mini and commented out the default layout.
If i press the first button keybow presents a '0', the second button a '1' but the third button presents a '4' - but the layouts/mini only talks to 0,1 & 2 so can't fathom where the 4 is coming from (i.e. expecting 2?) - I hope this makes sense to someone!
Made a fresh install of Keybow OS on a Keybow (non-mini), switched keys.lua to the media keys template.
macOS saw the input device, and the keybow successfully booted up and lit LEDs correctly, but no buttons would work.
Same thing with Linux, on openSUSE Tumbleweed KDE
I've been hacking on a re-implementation of the keybow code base, cleaning up some of the inter-dependencies, and hopefully making it easier to maintain and extend, would be interested in having a discussion with folks at Pimoroni about whether this is a good fit for future development of the keybow application & firmware. My code is up at https://github.com/GothAck/keybow-firmware/tree/keybowng. Things that still need to be implemented: serial and file access. Things I'm working on adding: Bluetooth HID support so keybow can easily be used with at least Android phones, hopefully other bluetooth devices as well :)
I want to use a KEYMAP table to be able to keep LEDs, physical keys, and handlers in sync, so I need to edit only in one place, the KEYMAP table. As it turns out through a painful cycles of comment out, update sdcard, boot, wait for LEDs to light or not (fail), the Keybow's lua doesn't have a working loadstring()
.
The following code works on a Kubuntu lua 5.2.4, while the Pibow's lua 5.3 fails. As I don't have a mini-HDMI adaptor I cannot watch the console output (Wifi, remember???)
for keyno = 0, 11 do
loadstring(string.format("function handle_key_%02d(pressed); route(%d); end", keyno, keyno))()
end
Am I mistaken here or is there a problem with Pibow's Lua loadstring()
? If it's the latter, can we please get if fixed?
Alternatively, what about calling a generic handle_key(keyno, pressed)
when there's no handle_key_xx(pressed)
present?
I'm using keybow mini on pi zero W/H. Is it possible to use bluetooth instead of the usb-mini line to connect to PCs.
There are some build notes, and makefiles, but I don't see any documentation on how you compile this project into the initramfs in the sdcard folder. Maybe I'm missing something, but it would be useful to know how your process works end-to-end to be able to hack on this better.
Hi, Is it possible to change the USB desciptors on the keybow mini?
Specifically I've told i need to ' change the USB descriptors to report a BOOTMODE keyboard that uses a standard 8-byte report.' in order for it to work on the hardware i have.
Hi,
I was wondering if you can help. I'm trying to use Keybow to add a degrees C and =/- symbols to documents using macros of Alt and keypad numbers.
Alt 248 and Alt 241. Code Copied in below. For the +/- I get an double entry one on key press and one on key release. The degrees C symbol seems to jump back to the start of the line.
Any guidance would be great.
Thanks
Gavin
require "keybow"
-- Standard number pad mapping --
-- Key mappings --
state = 0
function setup() -- Set custom lights up
keybow.auto_lights(false)
keybow.clear_lights()
state = 0
keybow.set_pixel(2, 255, 0, 0) -- Red
end
function handle_key_00 (pressed)
if state == 0 then
keybow.set_key("0", pressed)
if pressed then
keybow.set_pixel(0, 255, 255, 255)
else
keybow.set_pixel(0, 0, 0, 0)
end
end
if state == 1 then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key(keybow.KP2)
keybow.tap_key(keybow.KP4)
keybow.tap_key(keybow.KP8)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
keybow.set_key("C", pressed)
end
end
function handle_key_01(pressed)
if state == 0 then
keybow.set_key(".", pressed)
if pressed then
keybow.set_pixel(1, 255, 255, 255)
else
keybow.set_pixel(1, 0, 0, 0)
end
end
if state == 1 then
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
keybow.tap_key(keybow.KP2)
keybow.tap_key(keybow.KP4)
keybow.tap_key(keybow.KP1)
keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
end
end
function handle_key_02(pressed)
if pressed then
state = state + 1
if state == 1 then
keybow.set_pixel(2, 0, 255, 0) -- Green
end
if state == 2 then
keybow.set_pixel(2, 0, 0, 255) -- Blue
end
if state == 3 then
keybow.set_pixel(2, 255, 0, 0) -- Red
state = 0
end
keybow.sleep(500)
end
end
Should be media_keys
https://github.com/pimoroni/keybow-firmware/blob/master/sdcard/keys.lua
Hey there! Maybe I'm missing something but trying the following on a Keybow mini didn't load the patterns as expected:
keybow.load_pattern("rainbow.png")
keybow.load_pattern("patterns/rainbow.png")
keybow.load_pattern("patterns/rainbow")
local pattern = require "patterns/rainbow.png"
keybow.load_pattern(pattern)
Could someone explain what the correct syntax is for this please?
I am using the Keybow attached to a powered USB hub.
When I detach and then reattach the hub from the computer (Windows 10), the Keybow does not re-register. I need to detach and reattach the Keybow itself (i.e. reboot it).
This is with the pre-built image from the sdcard folder
If I install Raspian (Buster) on the Keybow, then clone, build and run the keybow binary directly, the detach/reattach via the hub works as expected.
This suggests (to me) that there is something missing from the cut-down Linux.
I'm having fun with the project but I don't see anything to play with GPIO in the current LUA api. How can I read and write GPIO?
Thanks.
I have a keybow that started to behave erratically with button 11. I am not an efficient lua programmer so initially I thought the problem was in the code. After a while I realised I could replicate the behavior by pressing the buttons harder or simply touching the keybow on the side, or slightly pulling the USB cable.
I did some investigation and, I might be wrong, but it seems that the black metallic pylon with the nut is short circuiting the contacts of key 11 right and key 8 left. The nut is not a zero ohm connection but it does conduct, especially when mechanically pressed.
Am I the only one experiencing these problems?
This is a feature request to add an editor to the 2020nov firmware image, and some hooks to permit persistance of modified files.
An example implemention is attached to this issue.
Thanx,
Peter
References:
the 2020nov firmware I'm building against: https://gist.github.com/Gadgetoid/f2ff7f3854a7a102074e8daf458063f5#file-keybow-wifi-zip
editor command "busybox vi" from the statical build of busybox suitable for raspbian 10 (mind the SYSV variant of EABI5 elf format!) http://mirrordirector.raspbian.org/raspbian/pool/main/b/busybox/busybox-static_1.30.1-6_armhf.deb
overlay trees for above firmware and its initrd with initrd rebuild instructions (incl. busybox binary, not installed as a package, w/o busybox convenience symlinks)
MOD.txt
MOD.zip
The learning guide ( https://learn.pimoroni.com/tutorial/sandyj/setting-up-the-keybow-os ) say: "The animations are displayed at 30fps."
The code (and comment) in file keybow/keybow.c say 60 in function void *run_lights(void *void_ptr){
Hi,
KeybowOS is designed to run entirely in RAM in order to reduce SD card wear down.
With this in mind, it would make sense to be able to use the Raspberry Pi Zero's USB device boot mode, in order to skip the SD card entirely:
When this boot mode is activated (usually after a failure to boot from the SD card), the Raspberry Pi puts its USB port into device mode and awaits a USB reset from the host. Example code showing how the host needs to talk to the Pi can be found here.
ie : plug Keybow to computer with no SD card, Keybow goes into device mode, computer sends KeybowOS/firmware, Keybow boots and appears as USB device (keyboard).
One could even automate sending KeybowOS from the computer.
I had a look, there are some references to the SD card in the RAM FS used in KeybowOS:
the init
in the initrd
creates /dev/mmcblk0p1
and then mounts it on /boot
.
I'm pretty new at this, so is this a way to pretend there is an SD card with mknod
and then using it? Or does this depend on the actual SD card being there to work?
Further reading of Pimoroni's rpi-ramdisk documentation, used to build KeybowOS, would make me think that a/ mknod
is indeed used to create a partition for raspbian to be happy with, even though there is no actual underlying SD card and b/ that it should really not be too hard to use a Keybow with no SD card.
Having more info on how keybow-firmware
is built (cf. #42 ) would be helpful here.
Lastly, for what it's worth, i did try to start the Keybow by booting it with rpiboot -d keybow-0.0.4
. The files are sent and the Keybow appears to boot, but it's never picked up as a USB device by my laptop:
sudo ./rpiboot -d ../Keybow/keybow-0.0.4/
Waiting for BCM2835/6/7/2711...
Sending bootcode.bin
Successful read 4 bytes
Waiting for BCM2835/6/7/2711...
Second stage boot server
File read: config.txt
File read: start_cd.elf
File read: fixup_cd.dat
File read: config.txt
File read: config.txt
File read: cmdline.txt
File read: kernel.img
File read: initrd
File read: bcm2708-rpi-0-w.dtb
File read: config.txt
File read: overlays/dwc2.dtbo
Second stage boot server done
Thanks!
I wanted to use the Keybow to allow me to easily type symbols from other languages (ᚠᚢᚦᚨᚱᚲ). Turns out, this is more difficult than expected as they are not part of the key codes set of a USB keyboard. These symbols are part of the Unicode character set but there is currently no way of typing these in the Keybow firmware. The USB HID documentation mentions a Unicode Page which could possibly be used to implement this.
Unicode input also has many other possible applications, such as math symbols, graphical symbols for ASCII art and emojis (Just imagine being able to type 💩 with the press of a single key!).
I flashed the custom KeyBow OS on a 32 GB SanDisk Extreme micro SD card, I have tried two different ones. This card works for every other OS I have tried except this one. When Connected to a monitor the rainbow screen appears and that's all.
I've got a number of commands in my IDE that require consecutive keystrokes e.g. ctrl + T, T. I've tried the following, but only one keypress reaches my computer. Could anyone provide examples of how this could be done?
function handle_key_01(pressed)
if pressed then
keybow.set_modifier(keybow.LEFT_CTRL, keybow.KEY_DOWN)
keybow.tap_key("T", pressed)
keybow.sleep(500)
keybow.tap_key("L", pressed)
keybow.set_modifier(keybow.LEFT_CTRL, keybow.KEY_UP)
end
end
function handle_key_02(pressed)
if pressed then
keybow.set_modifier(keybow.LEFT_CTRL, keybow.KEY_DOWN)
keybow.tap_key("T", pressed)
keybow.sleep(500)
keybow.tap_key("T", pressed)
keybow.set_modifier(keybow.LEFT_CTRL, keybow.KEY_UP)
end
end
The SD card contain the following dtb where maybe only those for PiZero (and 3A?) that support Gadget mode on USB are useful:
A few bytes could be saved here.
Since the keybow hw uses a Raspi 0WH, would it be possible to edit and test keyboard layouts via WiFi while the keyboard is acting as HID via USB? Is it possible to smb mount the keyboard layout lua scripts on the host via WiFi?
When I use macros or snippets that use set_modifier()
, the macro will run twice. It seems to be running once when I press the button down then again once the button is released. this doesn't happen when I use the set key modifier by itself.
I would like to implement (macro) key repeat and long key presses. Any chance for some kind of timer support?
I would like to use it during the boot, to access the bios, and other pre-OS options, but I did not find the way to let it work.
I noticed that as soon the password is asked to login in the OS, the 12-key keybow works, but not before, during the boot..
any idea to solve?
Hi, does anyone know of any way to emulate these keys?
I'm trying to add some extra controls to a KVM and those are quite often used
For ease of deployment, the firmware release should be distributed as a separate zip file that can just be extracted directly onto the SD card.
Admittedly this project is called keybow, but would anyone be opposed if I put up a PR with mouse support of movement and buttons?
I needed it for a use case so I hacked it into the USB HID announcement and underlying code, and I have it working locally.
Currently it supports right/left/middle mouse clicks (and holds), and movement in pixels.
While the file keybow-firmware/keybow/default.png is nice looking, it does not seems to match the size "required" and used in the sdcard distribution, like keybow-firmware/sdcard/default.png
In particular, it is 40400 while other in patterns are 12200 or 12400 or 1200 or 1*400.
As the title states - been using a keybow on Pi4 for a while with another keyboard attached via a Logitech unifying receiver - all is good.
However if I detach the unifying receiver and reboot the pi, the keybow ceases to work - latest fully updated buster image.
Thinking of moving my setup to a 3a+ which has only one USB port this isn’t going to go well if its not going to work by itself (I don’t need a standard keyboard - keybow literally sends mpd commands and calls scripts for me)
Any help in getting keybow identified and working by pi as a solus device ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.