Ps2 – Communicate with a PS/2 keyboard or mouse

Ps2 implements the PS/2 keyboard/mouse serial protocol, used in legacy devices. It is similar to UART but there are only two lines (Data and Clock). PS/2 devices are 5V, so bidirectional level converters must be used to connect the I/O lines to pins of 3.3V boards.

class ps2io.Ps2(data_pin, clock_pin)

Create a Ps2 object associated with the given pins.

  • data_pin (Pin) – Pin tied to data wire.
  • clock_pin (Pin) – Pin tied to clock wire. This pin must support interrupts.

Read one byte from PS/2 keyboard and turn on Scroll Lock LED:

import ps2io
import board

kbd = ps2io.Ps2(board.D10, board.D11)

while len(kbd) == 0:


Deinitialises the Ps2 and releases any hardware resources for reuse.


No-op used by Context Managers.


Automatically deinitializes the hardware when exiting a context. See Lifetime and ContextManagers for more info.


Removes and returns the oldest received byte. When buffer is empty, raises an IndexError exception.


Sends a command byte to PS/2. Returns the response byte, typically the general ack value (0xFA). Some commands return additional data which is available through popleft().

Raises a RuntimeError in case of failure. The root cause can be found by calling clear_errors(). It is advisable to call clear_errors() before sendcmd() to flush any previous errors.

Parameters:byte (int) – byte value of the command

Returns and clears a bitmap with latest recorded communication errors.

Reception errors (arise asynchronously, as data is received):

0x01: start bit not 0

0x02: timeout

0x04: parity bit error

0x08: stop bit not 1

0x10: buffer overflow, newest data discarded

Transmission errors (can only arise in the course of sendcmd()):

0x100: clock pin didn’t go to LO in time

0x200: clock pin didn’t go to HI in time

0x400: data pin didn’t ACK

0x800: clock pin didn’t ACK

0x1000: device didn’t respond to RTS

0x2000: device didn’t send a response byte in time


Returns the number of received bytes in buffer, available to popleft().