I made new Model F output PS/2

Arkku

02 Jul 2026, 00:28

Hi,

Some of you may remember from the new Model F megathread that I have made my own keyboard firmware (USB and key processing implementation from scratch), which also supports the new Model F keyboards. Anyway, one ambition I've had for this firmware was PS/2 output, since I'm also into retrocomputing and would like to use a "Model F" keyboard on vintage computers.

Well, I seem to have finally managed to do it: it just needs two free GPIO pins on the microcontroller, which the xwhatsit/wcass controller has (even conveniently located on a 6-pin header on the side), and either a PS/2 cable/connector wired directly to those, or (what I did) those pins can be wired to the USB connector's D+/D- pins and then one of those old passive USB to PS/2 dongles from the 90's can be used to share the same connector. (The dongles often came with early USB mice, and have the picture of a mouse on them, but they are just passive adapters and the PS/2 mouse and keyboard don't differ electrically at the connector.)

I tested it on a real IBM PS/2 as well as on my own earlier PS/2 to USB converter (yeah, it makes no sense to output PS/2 only to convert it back to USB, but for science (and debugging)), and commercial PS/2 to USB converter. After some initial mistakes and breaking out the logic analyzer (that I seldom bother to use, but really should do more), I think I have a pretty much complete emulation of the IBM Model M PS/2 keyboard that I used as reference, including all three keysets (many commercial keyboards don't even bother to support keyset 3 because Windows doesn't use it (probably because keyboards don't implement it), but I think Linux might benefit).

It's GPLv3 open source of course, but highly experimental at this point. Still, if anyone here would be interested in using it, e.g., for retrocomputing or some other use where it would actually get some testing, I would be delighted to help you set it up. Easiest would be for one of the AVR-based "Brand New Model F Keyboards" where I can tell you exactly where the wires for the PS/2 need to go, but it should in theory work on any AVR-based keyboard that is supported by QMK if you feel comfortable finding the pins on the PCB and soldering to them in case there is no easy-access pin header like on the Model Fs. (I would need to first port the keyboard support from QMK to my firmware, but that should be relatively easy, as I've set up a compatibility layer that takes the key matrix and LED/RGB/EEPROM/etc. access from QMK as is, and then replaces their USB and keycode/layer/macro handling completely with mine).
Attachments
ps2_input_to_ibm_ps2.jpeg
ps2_input_to_ibm_ps2.jpeg (672.78 KiB) Viewed 1649 times
modelf77_ps2_output.jpeg
modelf77_ps2_output.jpeg (686.96 KiB) Viewed 1649 times

Rico

04 Jul 2026, 16:19

This is an incredible job that you did !
I have yet to finish my work on PS2 compatibility for the Leyden Jar and your contribution is very inspiring, thank you :)

Arkku

05 Jul 2026, 02:31

Thanks! My PS/2 implementation itself is open source, so it should only take about 100 lines of code to use it on Leyden Jar. (I will probably implement Leyden Jar support in my own firmware as well, once I get my hands on one of the Leyden Jar controllers. I much prefer my firmware's key mapping and USB implementations to those of QMK.)

But the PS/2 code itself is very isolated, so if you want to take `ps2_output.c` and the supporting headers, and `usb2ps2_keys.c` for the scancodes, you just need to replace `kk_ps2_avr.h` with an ARM equivalent (<100 lines of simple code), and then have something in the main loop call `ps2_output_task()` and the thing that sends keypresses and -releases to USB needs to instead call `ps2_press_key(usb_keycode)` and `ps2_release_key(usb_keycode)`. That's pretty much it.

There are a ton of special cases in PS/2, so I had AI generate very extensive unit tests for them based on various implementation notes (e.g., Microsoft's PS/2 documentation from around the year 2000), and then even more by recording the raw output of various corner case keystroke sequences from an IBM Model M PS/2, so I"m not fairly confident that my implementation should match the Model M.

BTW, may I ask how do you plan to handle the PS/2 5V levels with RP2040, which AFAIK is not 5V tolerant, at least officially? The first solution that comes to mind is to just pull it up to 3.3 V on your side and let the host pull it to 5 V (as it will) on theirs, but that might prevent autodetection of the host (which is normally easy because the pull-ups are on the host side) and/or sharing the USB connector. But I am not an electrical engineer, so curious to know if you have found a solution for this?

Rico

05 Jul 2026, 16:31

Thank you very much for your feedback !

I will look at how you implemented the integration to your QMK like firmware and also the HID scancode to PS2/AT scancode conversion.
For the PS2 protocol I started basing my work long time ago on an open source project that implements it specifically for the RP2040 using PIOs:
https://github.com/No0ne/ps2pico

My goal is to integrate the PS2 feature in my VIAL fork and be able to easily shift from USB connectivity (to be able to tune keys/macros/layers with VIAL app) to PS2 by connecting the USB cable either to the Leyden Jar controller or to the PS2 daughterboard.

As for handling the 5V, I made a specific daughterboard that connects in place of the solenoid, it is described in my Gihub repository here (have a look at the end of the readme):
https://github.com/mymakercorner/Leyden_Jar

This daughterboard have 5V/3.3V level shifters for both clock and data lines.
And the 5V goes to the 3V3 voltage regulator to correctly power the Leyden Jar.

Arkku

05 Jul 2026, 17:00

Interesting about the daughterboard: does the USB-C connector on it only output PS/2 or does it also carry a duplicate of the actual USB? If the latter, how do you detect whether USB or PS/2 is connected to that shared connector?

(re. ps2pico, it is an extremely minimal implementation, as per "pico" name. It probably works fine in practice most of the time, but definitely won't match an actual PS/2 keyboard like the Model M.)

Rico

09 Jul 2026, 13:29

The USB connector only output PS/2, in fact it shares the same connector with the solenoid daughter board so it is either use the solenoid or PS/2.

As for ps2x2pico I don't know how far the developer went compared to your implementation to be honest, but it looks like he tested his implementation quite well (he even spotted a small implementation detail to work with SGI O2 workstation).
I will definitely look at what you did to try to improve the implementation.

Arkku

10 Jul 2026, 20:53

Would the daughterboard be compatible with the xwhatsit 6-pin side header as well, if it doesn't support combined USB / PS/2 connector? Can you tell me the pinout so I can set the same pinout as the default of my PS/2 output?

re. ps2x2pico, my earlier comment was based on the ps2pico (which is different) that you linked. That one is extremely minimal, no special cases or alternate scancode sets at all. The ps2x2pico is more complete, but I believe it is still missing the tenkeys virtual shift logic depending on num lock state. I believe my implementation should be pretty much indistinguishable from a real IBM Model M when all features are enabled. I made scancode sets 1 and 3 optional, and now I actually also made the virtual shifts optional. (I also have dozens of of unit tests, verified manually against IBM Model M, and I do believe my code is more "architectured". But might produce a bit larger compiled size as a result.)

Meanwhile I have ported Vial to my firmware (rather than port my PS/2 to QMK). I have managed to squeeze full PS/2 implementation together with Vial if Vial combos, macros and space cadet keys are not supported. With combos added, PS/2 needs to be turned down to as minimal as ps2x2pico, which is why I made the virtual shifts optional as well.

I will release a beta of my Vial firmware soon-ish!

Rico

10 Jul 2026, 22:51

The daughterboard is pin compatible with the solenoid wiring but uses additional pins in the IO expander that is in the Leyden Jar controller.I plan to remove those additional pins in a later revision of the daugherbaord so that it is fully compatible with the connector of the solenoid driver.
But the daugherboard has level shifters that will make it not work with an ATMEGA I believe, so there would be a need to make another daughterboard for the XWhatsIt controller anyway.

I started to see in your code that you went pretty far in IBM PC compatibility ;)
No sure I will commit to this path, at least at first (I don't have the hardware to test this anyway), I need first to validate that the code works and more importantly that the daughterboard itself works.

Arkku

Yesterday, 01:24

Ah, ok, too bad the daughterboard won't be compatible with the xwhatsit controllers, but I understand the need for level shifters (just forgot about them in the last message).

My preferred way is anyway to use the same connector as USB, so there is no need to add an additional hole in the case (or to run thin wires out of some opening not meant for that), I would recommend looking into that if possible, e.g., you could run a short wire from the USB output into the daughterboard for input and then output from another USB connector, avoiding the need for soldering.

Now that I've been porting Vial to my firmware, I have really had to get into micro-optimization to fit everything together with PS/2, so it would be a great fit for the Leyden Jar to use the full PS/2 implementation when it would have no problem fitting. (As said, I will add Leyden Jar compatibility to my firmware once the controller arrives so maybe someday next year we will anyway have that, but I didn't order a PS/2 daughterboard – not sure if it is even available yet.)

Rico

Today, 17:28

If the PS/2 daughterboard works I'd gladly send one to you :)
I find your project to not depend on QMK/VIA(L) repository very cool ;)

Post Reply

Return to “Keyboards”