In the last week I bought myself a small computer called a [neptUNO](https://www.antoniovillena.es/store/product/neptuno/) that has an FPGA (aka - to me - replicate retro computing hardware - [see more here](https://duckduckgo.com/?q=what%27s+special+about+fpga+retro+computers\&t=ffab\&atb=v215-1\&iar=videos\&iax=videos\&ia=videos)).

The ports on the machine are suitably old and include: VGA out, DB9 for joysticks/joypads and two PS/2 ports for keyboard and mouse. The device does actually have a USB port, but thus far I can’t find anything that works with it. So I bought myself a cheap PS/2 keyboard so I control the menu (selecting cores and ROMs) and of course the damn keyboard wouldn’t work (turns out the cores needed pull resistors on the PS/2 inputs).

I had a choice: I could ether solder two 5-10K resistors to the newly purchased neptUNO (my soldering skills aren’t great and could easily end up melting something I shouldn’t)… or I could build myself a remote PS/2 keyboard - which is what I did… of course!

[I’ve published 38 videos for new developers, designers, UX, UI, product owners and anyone who needs to conquer the command line today.](https://training.leftlogic.com/buy/terminal/cli2?coupon=BLOG\&utm_source=blog\&utm_medium=banner\&utm_campaign=remysharp-discount)

TL;DR[](#tldr)

  • [Video demo](#demos-first)

  • [Parts and source code](#code-and-parts)

But do have a read too, it was fun to make :)

Demos first[](#demos-first)

![ps2 connector with mounted buttons and esp module next to web page to control](/images/ps2-remote/finished1.jpg)

How it works[](#how-it-works)

After seeing [Ben Eater’s video on PS/2 keyboards](https://www.youtube.com/watch?v=7aXbh9VUB3U) I knew that the scan codes for a keyboard should be re-creatable with something like an Arduino.

My version version was just that. I used a library called [ps2dev](https://github.com/Harvie/ps2dev) to send a clock and data signal for the up and down keyboard scan codes. Then I wired my arduino directly into the PS/2 port and turned on the neptUNO to test - immediately the menus were moving up and down: this means the entire thing had legs.

![An arduino wired directly into PS/2 ports](/images/ps2-remote/proto1.jpg)

The next part was how would I send the scan codes. It might have been enough to have a couple of hardcoded buttons for things like F12 (which brings up the core menu), but I wanted some freedom and I wanted to be able to type.

I had a few ESP based [WEMOS](https://www.wemos.cc/en/latest/) boards from failed previous projects and decided that I would use my [D1 Mini](https://www.wemos.cc/en/latest/d1/d1_mini.html) and program it to accept a WebSocket request. That WebSocket would then, in theory, forward keyboard scan codes to the PS/2 connection.

The wiring is relatively straight forward and the arduino code required is partly lifted from existing example code and partly me making small adjustments.

![WEMOS D1 mini acting as a remote PS/2 controller](/images/ps2-remote/proto2.jpg)

The code on the D1 mini comprised of the following (and I’ll include the full source at the end):

  • Connect the ESP to my local wifi network

  • Configure output pins for clock and data lines for PS/2 connection

  • Start a [WebSocket server](https://github.com/Links2004/arduinoWebSockets/)

  • On WebSocket message, forward each byte in the message to the PS/2 clock and data lines

I would also go on to upgrade this to include: serve a single HTML page on port 80 of the device.

The cleverness is added with the browser. As you might have seen from the video demo, I can use a browser - on any device - to send remote key press commands.

Since the browser object model gives me events for key down and key up, these map perfectly to how the PS/2 scan codes work. For example, typing the letter "G" (uppercase) is a sequence of: shift down, g down, g up, shift up.

This translates to six bytes: 0x12 ("make" shift), 0x34 ("make" g), 0xF0, 0x34 ("break" g), 0xF0, 0x12 ("break" shift).

Thankfully the web archive has kept an [old webpage containing a table of scan codes](https://web.archive.org/web/20070210083447/http://www.computer-engineering.org/ps2keyboard/scancodes2.html) that I mapped to event.code from the key down and key up events.

In addition to mapping modern codes to scan codes, I also added the ability to define keys as buttons (so that I could use the page on my mobile device) and added some relatively simplistic heartbeat checking so that if the connection is lost (due to a power cycle of the neptUNO) the web page would automatically reconnect.

This all worked perfectly, so it was time to move on to Prototype Three - the semi-permanent soldering of the board and connected to a male PS/2 connector so I could disconnect and reconnect easily. I also wanted two shortcut buttons for neptUNO specific functions (the core menu and the "scandoubler" key) and because I had two chunky push buttons to hand.

My soldering skills aren’t great (which also why I’d rather solder my own hack kit rather than more expensive computers), and the task took me a good few hours, but I was rather pleased with the outcome.

![Building prototype three](/images/ps2-remote/proto3.jpg)

The end result is a device that I can plug in, trigger the menu without a computer at all (i.e. if I’m just playing with a joypad and need the ROM load menu) or I can have full control using my desktop keyboard.

Code and parts[](#code-and-parts)

Finally, the full source code for both the arduino based project and the web page (and JavaScript) that the device serves:

Note that the code to help you create your own thing, it’s possible you could copy and paste it but it’s not been written with that expectation.

Good luck and enjoy your own hacks.

👍 9 likes

[![Zack Boehm](/images/no-user.svg "Zack Boehm")](![@floehopper@fosstodon.org(/images/no-user.svg "@floehopper@fosstodon.org")](![Mahesh Jagadeesan(/images/no-user.svg "Mahesh Jagadeesan")](![Datamosh(/images/no-user.svg "Datamosh")](![Luke Browell(/images/no-user.svg "Luke Browell")](![Miikka Tuominen(/images/no-user.svg "Miikka Tuominen")](![Andy Buckingham(/images/no-user.svg "Andy Buckingham")](![liagason 👋(/images/no-user.svg "liagason 👋")](![Joshua Gilless(/images/no-user.svg "Joshua Gilless")](https://twitter.com/JoshuaGilless)

Comments

Lock Thread

Login

Add Comment[M ↓   Markdown]()

[Upvotes]()[Newest]()[Oldest]()

Humberto Möckel

1 point

4 months ago

Hi Remy, all! Inspired by this, I’ve just finished a Bluetooth version, that also works better on PC-compatible systems (ps2dev had many problems going past BIOS post). You can see a demo here: https://www.youtube.com/watch?v=2PVjWfAAJFE&ab_channel=Hambert and download the source from here: https://github.com/Hamberthm/esp32-bt2ps2

1 point

4 months ago

Awesome stuff 👍

Bradley R

0 points

4 months ago

within Setup()

while (keyboard.write(0xAA) != 0) { Serial.println("X"); } ; delay(40);

You see a ton of X’s until the pc reboots and ACK’s the keyboard? but mine still doesnt work, 8266 must be zapped

Bradley R

0 points

4 months ago

Hi Remy, Does this work to sync up with a PC’s ps/2 keyboard port? It has to listen and send something so the PC bios knows a keyboard is there? I got this working fully and its great, but after changing and uploading the code it lost the connection by keyboard port. I have the slave pc running notepad…​ unless I burned out my 8266. A buffer is a good idea. Seeking the code to listen and handshake, unless its there and I missed it? afaik the bios in the old pc-xt cannot be made to re scan for a ps/2 keyboard, the machine has to be rebooted?

0 points

4 months ago

The setup that looks for the 0xAA signal, I think is only sent by the PC during initialisation.

IIRC my implementation was fairly naïve and I’m sure I modified it specifically for my use case, so if you find it works better so some blocks commented out, then definitely take that route.

The bulk of my code is to do the translating across WiFi to the ps/2 port - the handshake itself is definitely brittle from what I recall.

Bradley R

0 points

4 months ago

Hi Remy great project! I did a similar one but used winforms and sent keys across the serial line, parsed and send out to ps/2. worked. then PC crashed and no backup. schematics were digitized and lost. soldering iron cord broke, magnifier glasses destroyed, uphill battle. Well finally went to say ok lets start over and saw your project, thank you! This is so cool because its a websocket? Hadnt done much with these 8266s and was able to get this spun up pretty fast, so cool!

Next step I hope to do is allow the code to be sent direct over the socket connection. In the old days it was easy, quiet work area hours at a time. Not like that now, may be 15 good seconds of focus time, 20 minutes of having to deal with something, ok where was I, 2 minutes, have to get up and deal with something. Just want to stick to this and finish.

D W

0 points

12 months ago

Michael, the ESP32 could do it, it has the bluetooth and there’s a library which does the input and pairing for you. https://github.com/turgu1/bt-keyboard. Now that’s the bluetooth part, just need the ps2 part…​ https://github.com/emard/esp32ps2 - you got that there. Just need to make a sandwich of these two pieces and you got what you want!

Wow, those things are cheap. I’ve ordered one and we’ll see how it goes.

0 points

15 months ago

\[X-Post from YouTube]

Michæl Alan Baker 45 minutes ago Intriguing; not exactly what I’ve been looking for but this might work, may even be better. I’ve actually been looking around for a somewhat similar solution; but rather I’ve been focused on a bluetooth solution. Forgive me, but I’m about to vent in your comments. 🤔 Basically, I want a device that would pair with any standard bluetooth keyboard using the BT HID profile and output the PS/2 keyboard protocol, thus allowing any device with PS/2 keyboard post support for a bluetooth keyboard. So far my search has been fruitless, I’ve found a few projects that due the inverse; connect a PS/2 keyboard (eg. IBM Model M) to a modern device (eg. tablet) via bluetooth. But mostly my search results are just inundated with USB Bluetooth adapters, all of which rely on the USB Host device to run the Bluetooth stack; which won’t work for my use case. I could maybe make a USB solution work if I could find one that ran it’s own BT stack and just showed up as a USB HID device but alas no luck either.\ My ultimate goal is to enable bluetooth keyboard support on my Commodore 64 (not a joke; I LOL when your video got to the C64 emulator demo. — Like many I love the C64, but after about 10 minute of typing on that keyboard and, the nostalgia really starts to wane but I really like tinkering with theoriginall hardware.) As you may well know, natively the C64 just uses one of its 6526 CIA chips (Complex Interface Adapter for 6502) to directly decode the keyboard matrix, but I already have a solution that interfaces itself between the C64 keyboard pin header and the lines coming from the key matrix that accepts and decodes a PS/2 keyboard connection and emulates the native matrix scan codes; enabling use of either the PS/2 ororiginall keyboard. I have a nice C64 bread bin that I’ve restored and I don’t want to put in hole in this one, hence the desire for a wireless solution. I’ve considered just using an old wireless PS/2 keyboard, but I not found one I really want to wed myself too. The cool thing about your solution is it opens up some other possibilities like sending keystrokes directly from a laptop or loading text files directly from a cell phone via just key emulation which could be useful. I expect youre aware the original C64 kernal doesn’t support anything like an AUTOEXEC.BAT or start-up script it just loads directly into the Basic shell so without a modified kernel starting up a C64 inevitability becomes a kind of ritual of initializing and reconfiguring things the way you want them especially when you have a lot of modes and peripherals. It would be super cool if I could just press a button on my phone and it would connect then send over and execute my standard set of boot commands. Plus it would be easy enough to capture key presses from a bluetooth keyboard paired with my phone and send them over; though I would prefer a way to pair a keyboard directly. . . Going to have to think about this a bit more.

conrad

0 points

2 years ago

Just let people know i encountered some problem and (likely) solve it.

I just use your esp code on a nodeMCU board, I changed clock and data pins to D5(14) D6(12) because it seems no pwm support for D1 on nodeMCU.

It’s works but only in bios and grub, not in windows 10 or linux(manjaro kde latest).

The port 60/64 emulation in bios is disabled by default.

Then i found that my old PS/2 keyboard works perfectly every time after booted into OS, and nodeMCU keyboard works too if i unplug the old PS/2 keyboard, wiring nodeMCU to PS/2 port.

That’s good enough for me, it’s totally usable now.

I think esp8266 boards with WiFi are perfect to make an wireless macro keypad on budget.

[Commento](https://commento.io)