Skip to content

matefon/PicoS2-MicroPython

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PicoS2-MicroPython

A robust PS/2 to USB HID keyboard converter for the Raspberry Pi Pico (RP2040), written in MicroPython.

Features

  • PIO-based PS/2 Driver: Uses the RP2040's PIO state machines for precise, non-blocking signal reading.
  • Asyncio Core: Fully asynchronous event loop handles USB reports and PS/2 events concurrently.
  • Robust Error Handling: Includes a watchdog to restart the PS/2 reader if it crashes and file-based logging (log.txt).
  • Status Feedback: Uses the RP2040-Zero's onboard NeoPixel for visual status indication.
  • Full Mapping: Supports standard keys, modifiers, navigation clusters, and numpad.
  • Easy macro definitions: Change macro definitions in keymap.py using Thonny.

Hardware

  • Board: Raspberry Pi Pico or RP2040-Zero (Code configured for RP2040-Zero NeoPixel on GPIO 16).
  • PS/2 Connector: Female PS/2 socket or breakout.
  • Level Shifting: PS/2 is 5V, Pico is 3.3V. While my testing keyboard works with 3.3V, a level shifter or voltage divider could be necessary.

Wiring (Default)

PS/2 Pin Pico Pin Function
5V VBUS Power
GND GND Ground
CLK GPIO 0 Clock
DATA GPIO 1 Data

Note: Pins can be changed in main.py.

Installation

  1. Flash MicroPython: Install the latest MicroPython firmware on your RP2040.

  2. Install Dependencies: You need the usb-device-keyboard library.

    import mip
    mip.install("usb-device-keyboard")

    In case it fails:

    • Close Thonny
    • run pipx run mpremote mip install usb-device-keyboard

    (Or copy the library manually if offline)

  3. Copy Files: Upload the following files to the root of the Pico:

    • main.py
    • ps2_pio.py
    • keymap.py
    • ps2_constants.py
    • usb_constants.py
    • simple_test.py (needed only if testing the PS/2 wiring)
  4. Change key definitions (optional): User friendly key/macro system defined in keymap.py. Edit in Thonny for example (hit Stop/Restart Backend until you see the terminal in which you could type).

  5. Run: Reset the board. It will wait 1 second (flashing yellow) before starting.

Status LED Codes (RP2040-Zero)

Color Pattern Meaning
🟡 Yellow Flashing Initialization / Waiting
🟢 Green Solid (Dim) Ready / Idle
🟢 Green Flash (Bright) Key Press Detected
🔴 Red Solid USB Error (Check connection)
🔴 Red Flashing PS/2 Error (Unknown key/Protocol error)

Debugging

  • Log File: Errors are written to log.txt on the device. Not cleared on startup unless DEBUG = True in main.py.
  • Debug Mode: Set DEBUG = True in main.py to log all events, not just errors. Clears on startup.

Some info about PS/2 protocol

Working keys

All keys are read correctly from the PS/2 keyboard. Even Pause/Break (it is special though: it doesn't have a release code so a press is a press-release and a release is unnoticed).

Not working with HID right now (out of the box): F13-F24 extended function keys. These are great for macro use in apps that support them, as they cannot be accessed (and be pressed) from most keyboards.

Extended function keys (F13-F24)

This is a MicroPython HID limitation. In micropython-lib/micropython/usb/usb-device-keyboard/usb/device/keyboard.py the _KEYBOARD_REPORT_DESC is using logical and usage maximum of 101. A value of 115 (x73) is needed for extended function keys to work.

How to fix:

  • Close Thonny
  • Install mpy-cross and mpremote with pip or pipx: pipx install mpy-cross mpremote
  • Optional: Download latest keyboard.py from https://github.com/micropython/micropython-lib/blob/master/micropython/usb/usb-device-keyboard/usb/device/keyboard.py and copy this into the repo lib folder; patch the file: modify b'\x25\x65' and '\x29\x65' to b'\x25\x73' and b'\x29\x73' respectively, and add F13-F24 keycodes (104-115)
  • Run this in the repo lib folder: mpy-cross keyboard.py
  • Optional: Save original keyboard.mpy: mpremote cp :lib/usb/device/keyboard.mpy original_keyboard.mpy (you can revert by re-installing the library, see above)
  • Copy the patched keyboard.mpy: mpremote cp keyboard.mpy :lib/usb/device/keyboard.mpy
  • Reboot the Pico.
  • Test the extended function keys (remember to change some key definitions first then reboot the Pico): pipx install hid-tools then run hid-recorder and select MicroPython Board in FS mode

Note: precompiled patched keyboard.mpy is available in the repo lib folder.

Note: on my KDE Ubuntu 25.10 system, extended function keys are interpreted differently (F14 as XF86Launch5, you can check this with xev -event keyboard or evtest). You can try to fix this with assigning the keycode (the number xev showed you) to the key:

e.g. xmodmap -e "keycode 184 = F14" (not tested) or use xkb/xmodmap.

Todo

  • Add SSD1306 support
  • Add onboard menu for changing keymap, macros and providing feedback
  • Add EC11 rotary encoder support (for onboard menu navigation)
  • Add Rubber ducky functionality, accessible from onboard menu and as macro definitions
  • Define keymap in JSON so it is more readable and can be changed from onboard menu
  • Add a button/switch to trigger HID only mode (no MicroPython) to increase compatibility
  • Add hardware (MOSFET/BJT) and software (is it possible with current PIO? Maybe 2 other control pins for transistors) to control the PS/2 keyboard onboard LEDs (CapsLock, NumLock, ScrollLock)

I accept any help and suggestions.

Disclaimer: this project was created using AI (Claude Sonnet 4.5 and Google Gemini 3 Pro (Preview) in VS Code). This is hobby code, usage of AI speeds up development drastically.

About

RPi Pico macro-keyboard project which uses a PS/2 keyboard's input to send keystrokes to the computer. In MicroPython for convenience.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages