Using a PS/2 keyboard with Raspberry Pi GPIOs

Why?

Maybe you want to free up a USB port (especially on Pi-zero or Pi-aplus).

Maybe you have piles of PS/2 keyboards gathering dust (perhaps one is a much treasured Model-M).

Maybe you are writing your own OS and want keyboard access without having to write a full USB stack.


Background

The Raspberry Pi is great for hacking with, but it is hard to get keyboard input without using USB. If you're running Linux that's not a problem, but if you're running your own operating system it's a problem, especially if you don't feel like writing a complete USB stack.

The PS/2 keyboard interface is a very simple serial protocol, so I wanted to design a board that would take a traditional PS/2 keyboard and convert it to something that could be read with standard Pi GPIOs.

This will be useful for the Advanced OS course I teach, as it is easy to get video output going but until now we couldn't get keyboard input, only serial port which can be a bit awkward (you need another machine around to use your OS).


The PS/2 Interface

The PS/2 interface is a simple serial interface. It is an open-collector bus and you can send commands to the keyboard (set repeat rate, turn on caps-lock LED, etc.) or get values upon keypress.

The values you get are encoded a bit, and you generally get two actions for each keypress (once when it is pressed and once when released).

For more info I recommend the following sites:

The pi-ps2 Adapter Board

The adapter maps the clock and data lines from the keyboard to two Raspberry Pi GPIOs.

The Pi wants 3.3V I/O, so the board includes a logic level converter to drop the 5V signals from the keyboard to 3.3V.

The board is designed to be like a "hat" so you can plug the board to the GPIO header but still have access to all of the GPIO lines. It uses GPIO 23 and 24 by default, but the connection is jumpered so you can disconnect from those pins and use jumper wires to manually use any GPIO.

The keyboard is powered directly by the Pi. I've seen reports that a keyboard can draw up to 275mA so you might want to make sure you have a strong enough power supply.

The connector has a traditional DIN-6 PS/2 connector for the keyboard. Many USB keyboards support a legacy PS/2 mode (often these will come with "USB/PS-2 adapters" that are just straight through wiring of the PS/2 pins to the USB connector). Because of this the adapter has a USB connector so you can use these types of keyboards without the PS/2 adapter *NOTE* not all USB keyboards will work in this socket.

Frequently Asked Questions

  • Can I use a PS/2 mouse instead?
    Probably! It is untested and will of course require code to handle the protocol.

  • Can I hook up an arbitrary USB device to the port?
    No! Only keyboards (and even then only keyboards that handle fall-back compatibility to PS/2 mode)

  • Can I use a mouse and keyboard at the same time?
    Maybe! The bus is open collector, so in theory you could put a PS/2 mouse on the PS/2 connector and a supported keyboard on the USB keyboard and use both. You'd have to write a special driver to handle this case.

  • Can I use this on a Pi 2/ Pi B+?
    Yes! The header is narrow enough that it fits even on devices with 40-pin headers.

  • Is this a full hat, with eprom and autodetection of device-tree files?
    No! Maybe if I get really bored someday.

  • Is there a Linux driver for this?
    Yes! It is included with the source code.

  • Will this work on non-Pi embedded boards?
    The board is designed with the Pi GPIO header in mind. You could in theory hook up 5V, 3.3V and two GPIOs and use it with any board that has 3.3V GPIO but this is untested.

  • How much does it cost to build one?
    Roughly $11 each assuming you are making them in batches of 12. This will vary depending how cheaply you can source/scrounge the parts needed, and if you leave out optional parts.

  • Can I buy a kit?
    No, but I include the parts list and the gerbers in the source tree and you can order the board from OSHPark here.


    Driver Challanges

    The ps/2 protocol is very timing dependent. The 11 bits are clocked in at a rate of about 60-100usecs each, so you either have to interrupt on the first bit and then poll (causing your interrupt handler to have a latency of over 1ms, not good) or else have an interrupt on each clock signal (but then if you can't guarantee interrupt latencies of 50us or so you will miss bits and lose sync). There are a few ways to work around this:

    Source Code

    Some sample code for accessing this is available in my vmw-meter source repository under the pi-ps2 directory.

    Also included are the GEDA design files and gerbers.

    There is also a sample linux-kernel driver: pi-ps2gpio.c

    Related Work

    There have been similar PS/2 keyboard projects over the years, but as far as I can tell none specific to the Pi (most are for PIC and other microcontrollers). And none use both generic GPIOs while providing a Linux driver.


    Build Log

    12 January 2016

    For those of you who only interact with the world through videos, I've created a video for the project. It's hard making keyboard usage interesting.


    8 January 2016

    Working on driver for VMWos. Complicated as it involved writing a GPIO library, and then migrating the UART code to be interrupt driven and then providing a console input abstraction layer.

    It now works when using a serial port for output. Using the HDMI console is troublesome as current code spends so much time drawing characters to the screen that interrupts are missed and the keycodes get corrupted. Real solution is probably to enable L1-cache/MMU but that might be a bit of work.

    7 January 2016

    Linux driver is a bit hackish but it works.

    6 January 2016

    Working on writing a Linux kernel driver. Turns out to be easier than I thought it would be.

    4 January 2016

    The boards are back already! That was quick.

    Here it is assembled, front and back:


    And here it is hooked up to a Pi-Bplus. Remarkably it worked first try!


    Well, mostly works. I'm actually impressed trying to bitbang the interface from userspace works at all. Need to get one of the existing gpio/ps2 kernel drivers installed, or else write a driver for my OS.


    22 December 2015

    Made a PCB via GEDA and sent it off to OSH Park to get made. We'll see how that goes. Some annoying complications as the DIN6 footprint I made was using the pin numbers from the top whereas the datasheet was labeling from the bottom, but I think I got it all sorted out properly before sending it off. We'll find out in 2-4 weeks.


    18 December 2015

    Got keyboard input working via the GPIO lines! Adding external pullup resistors helped a lot.


    17 December 2015

    Hooked up the board to the oscilloscope to make sure it all worked at least at the hardware level.


    Success! Here it is showing the proper output when a 'V' is pressed. Now just need to get the Pi reading this over the GPIO ports.


    16 December 2015

    Soldered together a prototype of the adapter board. Ruined a PS/2 connector trying to solder the tiny wires, in the end used an IDC connector/socket even though it's more expensive that way.



    Back to VMW hardware productions