Help running kbdgfx


I’m trying to put some image into my Pocket OLED by running the kbdgfx utility.

Using the script:

  • Imagemagick complains about font being not set, I replaced Inter-Bold.ttf by Inter-Bold and stopped complaining.
  • kbdgfx complains with the size put on the script of 126x32 pixels with Couldn't read bitmap or wrong size. I modified the script to 128x32 pixels and it does not complain anymore (?).
  • I checked that the imagemagick convert command generates the expected image, by temporarily substituting gray:temp.bin for temp.jpg and checking that the built image is a black background with the specified text (“hello”).
  • I think the specified device is the correct one because there is no other /dev/hidraw* on the system.

I run the script with ./ /dev/hidraw0 8 "hello" and nothing shows on the OLED screen, neither kbdgfx complains.

1 Like

I suspect there’s some changes between the keyboard firmware on the Pocket (which uses a RP2040 firmware) and the reform2 keyboard (both the original and replacement one use atmega32u4). I’m running a slightly older firmware on mine that expects the 126x32 graphics still so I modified kbdgfx.c to be 126 wide instead of 128 (128 results in a skew). I did have to do the same change to with removing ttf from the font, but otherwise it works fine for me on an original reform. For me the correct hidraw device was /dev/hidraw2.

I thought the two firmwares had all the same commands but perhaps there’s a bug in the RP2040 pocket version or the command hasn’t been implemented yet to do custom drawing.

I haven’t tested this, but there is also a kbdgfx.c in the pocket reform repository. The command it is sending to the keyboard is XRGB.

Looking in the firmware (main.c), the command XRGB pushes a bitmap to the keyboard backlight?? (cool!) Not the OLED.

To send a bitmap to the OLED the pocket firmware seems to expect WBIT just like in the non-pocket reform. So in principle we should be able to do this but the old kbdgfx may need to be updated (it would be nice if they had different names :slight_smile:)

I can try to debug this over the weekend.

Thank you for your feedback.

I tried again with the utility from the Pocket repository, and it still does not work, as expected by your explanation about it sending the keyboard backlight instead of the OLED.

I don’t understand C code, but the pocket kbdgfx utility has reference to rgb, while the one for the original reform has references to a bitmap of 126x32 and gray/8 bits depth, as you explain.

I’m looking at the keyboard firmware code for the pocket keyboard and as far as I can tell it should still support the exact same xWBIT command that the kbdgfx.c for the regular reform sends.

The one thing I did notice though is that matrix_render_direct requires the first byte sent in the buffer to be 0x40, while on the original mnt keyboard that requirement is not there, and there’s a FIXME in the code about it. So if we modify kbdgfx.c to include that byte at the beginning it’ll likely work. But this really should be fixed at the firmware level ideally so that both have parity.

I quickly hacked up a version of kbdgfx.c to add that but I don’t have a Pocket Reform to test it on if you want to give it a try: Pocket Reform KBDGFX.C Test Fix ($8) · Snippets · GitLab

1 Like

Yes I just saw this as well and tried to send the 0x40 byte in the data as you suggested.

But it looks like there may be other problems in the matrix_render_direct implementation in the pocket reform.

I think MatrixRows should replaced by DisplayHeight here:

i2c_write_blocking_until(i2c0, SSD1306_ADDRESS, bitmap, 1 + MatrixRows * DisplayWidth, false, make_timeout_time_ms(OLED_I2C_TIMEOUT));

And the commands to move to the home position maybe should be:

send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1);
send_cmd3(ColumnAddr, 0, DisplayWidth - 1);

I can try to compile a new firmware with these changes.

As talked with Chartreuse on IRC, for some reason we have not been able to send commands to the hidraw device.

For example, he asked me to send this command, which should have cleared the OLED (the menu was being opened at that moment) with echo -n 'xWCLR' | sudo tee /dev/hidraw0, but the command didn’t work.

I don’t believe it should be displayHeight as the data is sent packed in 8 pixel tall sections, which is basically the raw format of the device. Rather than an intuitive horizontal layout. It’s a 128x32 b&w display, so it’d be sending 128 bytes (width) * 4 rows (of 8 pixels each)

EDIT: You can see the commands that the working Reform2 uses to drive the OLED, the screen is the same device between them, just a difference in keyboard microcontroller. reform2-keyboard-fw/oled.c · master · Reform / reform · GitLab

You are right!

So the extra 0x40 byte should be the only issue.
I don’t know why the OLED commands are not working. Sending LED backlight commands to hidraw0 does work (Change keyboard backlight from cmd line?).

Is it working for you to send any of the keyboard hidraw commands? Or is this bug limited to amospalla’s pocket here? I don’t have a pocket myself to test but on IRC had them try out a few other commands to no effect like xWCLR and xLOGO.

The hidraw commands that control the keyboard backlight ARE working for me. This includes the kbdgfx demo in the pocket reform repository.

But I dont think any of the hidraw commands that control the OLED work for me. I’ll double check…

It sounds like only mine fails.

I could try to reset the RP2040/System Controller, and check if that helps.

Is this accomplished by running the “reset keyboard” command on the OLED? I have already tried that.

To be clear, on my pocket (as root) this changes the keyboard LED color

echo -n -e 'xLRGB\x00\xFF\x00' > /dev/hidraw0

but this does nothing

echo -n -e 'xLOGO' > /dev/hidraw0

I reseted my Pocket by using the physical power switch (running keyboard reset from the oled menu was not enough) and now my Pocket accepts xRGB (but no xWCLR) and runs the kbdgfx demo from the pocket repository.

Still no luck with sending a bitmap to the OLED.

I think I found a bug in the pocket keyboard firmware.

In main.c
if (bufsize < 5) return;
makes it so the keyboard ignore strings/commands of length 4!

If I send ‘xLOGO0’ the keyboard plays the logo animation :slight_smile:
And ‘xWCLR0’ clears the OLED screen.

1 Like

This shouldn’t affect the original issue here of drawing a bitmap with WBIT because the data makes for a long command.

One more update.

echo -n -e 'xWBIT\x4099999999999' > /dev/hidraw0

does draw on the screen. A bunch of garbage but you can see the the pattern made by the 9’s in the top left of the screen. (the firmware blits the whole screen with data that happens to be in memory in the right place)

But @Chartreuse modified kbdgfx with the additional 0x40 did not work for me as is.

I think the modified kbdgfx should work, except that hidraw0 in the pocket seems to refuse commands that are ‘too’ long. kbdgfx makes a pretty long command with the image data.

If I repeat the echo command above with more 9’s (not enough to fill the screen…) I get a broken pipe.

Indeed, I can only send at most 64 byte commands to the pocket keyboard hidraw0 device – I am hoping there is a way to setup tinyusb to accept longer commands. I see there are lots of #define for various buffer sizes that are set to 64 by default.

1 Like