PRK is a keyboard firmware platform in PicoRuby


PRK Firmware (public beta)

PRK is a keyboard firmware written and configured in PicoRuby which is an alternative mruby implementation targeting on one-chip microcontroller.


  • A "keymap" can be configured in Ruby which is a concise, readable and happy language
  • RP2040 is the target platform microcontroller
  • You can write your own "action" which will be invoked when you tap or hold a key (example(TBD))


  • Raspberry Pi Pico
  • Sparkfun Pro Micro RP2040 (DEV-17177)

(left: Raspberry Pi Pico / right: DEV-17717)


  • Unsplit keyboard
  • Split keyboard
    • Symmetrical type. eg) Crkbd
    • Asymmetrical type. eg) ???
    • UART communication between left and right
    • I2C communication between left and right
  • Macros
  • Media keys
  • OLED display

Getting started


Fork, clone, patch and send a pull request.

For those who are willing to contribute to PRK or write your own keymaps:

  • It's possible that your Ruby code can't be compiled as you wish
    • Remember that "Ruby" in PRK is neither CRuby nor even mruby
    • PicoRuby doesn't support some Ruby syntax and may have bugs. It would be great if you send a patch, too!
  • Unlike QMK Firmware, prk_firmware repository doesn't include individual keymaps

Keymaps for example

  • Raspberrypi Pi Pico

    • PiPi Gherkin (coming soon)
  • Sparkfun Pro Micro RP2040 (DEV-17717)

To keyboard creators:

Feel free to reach out to me if you want me to link your keymap on this README.


  • Q: Can I use Sparkfun Pro Micro RP2040 as a drop-in replacement instead of a Pro Micro without having to modify the CRKBD PCB?

    A: Yes you can! However, note that RGBLED feature is still not implemented on PRK. And don't expect your existing CRKBS's LEDs will blink even if the feature is ready because the logic voltage of RP2040 is 3.3V while 5V on "normal Pro Micro".

    In terms of 3.3V, you should be careful of the same thing which is warned on Proton-C:

    Some of the PCBs compatible with Pro Micro have VCC (3.3V) and RAW (5V) pins connected (shorted) on the pcb. Using the Proton C will short 5V power from USB and regulated 3.3V which is connected directly to the MCU. Shorting those pins may damage the MCU on the Proton C.

    So far, it appears that this is only an issue on the Gherkin PCBs, but other PCBs may be affected in this way.

    In this case, you may want to not hook up the RAW pin at all.


Copyright © 2021 HASUMI Hitoshi. See MIT-LICENSE for further details.

  • Matrix to Layout Conversion

    Matrix to Layout Conversion

    Because the key matrix and the actual keyboard layout may be different, it would be nice to be able to write a keymap with a different layout from the key matrix, like the QMK Firmware layout macro.

    If the Ruby syntax can handle this, I hope you can provide a sample of how to write it.

    opened by e3w2q 20
  • Builds via Docker will not load onto the microcontroller

    Builds via Docker will not load onto the microcontroller

    When I download the most recent tagged release, 0.9.14 it works perfectly on my two Seeed XIAO RP2040 boards.

    I am quite excited by PRK and interested in poking at the source (and hopefully sending in some pull requests!). I can successfully run the tests and build the latest few commits to master with the Docker image. Unfortunately, when I load the built uf2 file onto either of my boards, the board will not mount the PRKFirmware volume. Unfortunately it seems something is corrupted in the uf2? (Thankfully I can reboot the board back into bootsel mode and load the 0.9.14 firmware again.)

    I am running a Mac with Intel Core i5 processor. Here's what I'm doing:

    git checkout master
    git pull master
    rake deep_clean
    docker compose build
    docker compose run --rm prk rake setup
    docker compose run --rm prk rake
    # steep checks pass
    # tests pass
    # binaries are successfully built
    # ...
    # [100%] Linking CXX executable prk_firmware-0.9.14-20220629-d921fc5.elf
    #   adding: prk_firmware-0.9.14-20220629-d921fc5.uf2 (deflated 73%)
    # [100%] Built target prk_firmware-0.9.14-20220629-d921fc5
    ls build
    # ... lots of things ...
    # prk_firmware-0.9.14-20220629-d921fc5.uf2
    # 👉🔘 Reboot Seed XIAO RP2040 into bootsel mode
    # Drag-and-drop flash_nuke.uf2 to /Volumes/RPI-RP2
    # volume unmounts, then mounts again
    # Drag-and-drop prk_firmware-0.9.14-20220629-d921fc5.uf2 onto the RPI-RP2 volume
    # The volume unmounts and then nothing happens.

    Please let me know if I can provide any other details. Thank you!

    help wanted 
    opened by rschenk 15
  • Only during the breath effect, the LED flickers for a moment periodically.

    Only during the breath effect, the LED flickers for a moment periodically.

    Only during the breath effect, the LED flickers for a moment periodically. It does not depend on the value of Hue or Speed, and may occur when Value is changed, but the reproducibility is not good. This phenomenon does not occur with other effects.

    opened by techmech-keeb 11
  • <<Request>> Macro keys

    <> Macro keys

    I would like to have a key where pressing it automatically writes ```, or some other list of characters. Composite keys seem close to what I want, but those press them at the same time instead of one after another. Is this possible?

    opened by SekoiaTree 11
  • Take out Joystick report

    Take out Joystick report

    Fix #148

    • To work with iPad, split HID interface for Joystick.
    • To work with Mac, send HID report only if the report changed except Joystick report.
    • Additionally, remove BIOS keyboard function because it was not working correctly.

    I checked this version works with iPhone 8.

    opened by yswallow 10
  • Cannot build on M1 Mac

    Cannot build on M1 Mac

    I get the following error.

    According to the error in Docker, the lemon (The Lemon Parser Generator) executable is not supported? I need someone else to try, as likely to be my shallow understanding or environmentally dependent. I have confirmed Hello World in Ruby and Blink in PICO SDK.

    opened by Taro-Hayashi 10
  • Problem with keymap not being recognized properly when connecting to Remap.

    Problem with keymap not being recognized properly when connecting to Remap.

    I used PRKFirmware 0.9.14 and created the Firmware using the following document.

    If I fill in the keymap directly in via_map.txt, it works fine. On the other hand, when I connect to Remap, the keyboard is detected by the information in prk-conf.txt, but the following anomaly occurs and I cannot change the keymap properly.

    • The keymap displayed in Remap is different from what I set.
    • When I edit the keymap in Remap and flash it, the changes are reflected in only some keys.
    • When I flash a keymap in Remap, the file is corrupted.
    • The key tester in Remap is not working.

    #Windows10 #Chrome (103.0.5060.114) #PRK Firmware (0.9.14) #keyboard:OLSK60 (Adafruit KB2040)

    opened by techmech-keeb 8
  • Implement Tone (formerly called PWM)

    Implement Tone (formerly called PWM)



    Set pin to use Tone.

    tone.set_tones( [ [tone1,tone_ms1], [tone2, tone_ms2], ... ] )

    Set tone sequence. (overwrites current sequence)


    Start sequence.


    true if any key in keyboard report, else false.


    tone_ms*tone < 1,000,000

    tone: 0 or >25


    require "tone"
    tone =
    tone.set_tones( [[349,250],[466,375],[440,375],[349,250],[0,125],[349,375],[392,1000], [0,125],[392,250],[523,375],[440,375],[392,250],[0,125],[392,375],[349,1000] ] )
    press = false
    kbd.before_report do
        if kbd.keys_press? 
            unless press
                press = true
                tone.set_tones( [ [440,50],[880,50] ] )
        elsif press
            press = false


    #32 #138

    opened by yswallow 7
  • Dockerfile fails

    Dockerfile fails


    Thanks for sharing your very interesting project!

    I m interested in building a binary but, I guess the instructions in the wiki will only work in linux right? for me reading about it for the first time it was not obvious I tried and fail miserable in Macos catalina (suggestion add some pointers for the environment and requisites).

    Then I tried and fail building the Dockerfile

    last messages:

    => => transferring context: 2B 0.0s => [build 2/16] RUN apt-get update && apt-get install --no-install-recommends -y 207.0s => [build 3/16] WORKDIR /prk_firmware 0.5s => [build 4/16] COPY . . 0.3s => [build 5/16] WORKDIR /prk_firmware/src/ruby 0.4s => ERROR [build 6/16] RUN bundle install 1.2s

    [build 6/16] RUN bundle install: #10 1.161 Could not locate Gemfile

    executor failed running [/bin/sh -c bundle install]: exit code: 10

    opened by pbrena 7
  • Wrong layer and modifier states

    Wrong layer and modifier states


    version: v0.9.12


    # Initialize a Keyboard
    kbd =
    # Initialize GPIO assign
      [ 27 ], # row0, row1,... respectively
      [ 6,7,8,9 ]  # col0, col1,... respectively
    kbd.add_layer :default, %i(
    kbd.add_layer :raise, %i(
      ________ KC_1 KC_2 ________
    kbd.define_mode_key :LAYER_C, [ :KC_C, :raise, 200, nil ]

    hardware: image

    How to reproduce

    1. press & hold KC_LSFT and...
    2. tap KC_A => A 🙆‍♂️
    3. tap KC_B => B 🙆‍♂️
    4. tap LAYER_C =>
      • expected: C
      • actual: reported nothing 🤔
    5. tap KC_A =>
      • expected: A
      • actual: 1 🤔
    opened by arai-ta 7
  • Users can change VID/PID/ProductName by `via-conf.txt`

    Users can change VID/PID/ProductName by `via-conf.txt`


    • In order to take advantage of the VIA feature (#57), VID and PID should be configurable
    • According to @yoichiro, Remap uses the "product name" in addition to the above


    • Dragging and dropping via-conf.txt file (then reboot the board) changes the values

    • The format of the content: [VID]:[PID]:[Product name]


    If via-conf.txt includes this content,


    these values are going to be applied as the image shows:


    opened by hasumikin 5
  • Dockerfile fails to build its container

    Dockerfile fails to build its container

    Hello PRK,

    I am interested in this next generation keyboard firmware!

    So I've tried the Dockerfile in 0.9.20, but it failed docker build. It seems to be a problem related to rake setup according the log.

    I would appreciate it if you could fix this error.

    Thank you.

    ~/prk/prk_firmware ❯❯❯ docker -v                                                                   ✘ 127 master ✱ ◼
    Docker version 20.10.21, build baeda1f
    ~/prk/prk_firmware ❯❯❯ docker build -t test:1.0 -f Dockerfile .                                          master ✱ ◼
    [+] Building 182.2s (12/13)                                                                                          => [internal] load build definition from Dockerfile                                                           0.0s
     => => transferring dockerfile: 658B                                                                           0.0s
     => [internal] load .dockerignore                                                                              0.0s
     => => transferring context: 2B                                                                                0.0s
     => [internal] load metadata for                                            3.3s
     => [auth] manjarolinux/base:pull token for [](                                               0.0s
     => [1/8] FROM  17.3s
     => => resolve  0.0s
     => => sha256:41ecfa93b6e0ebbc1d8f539fd538fc6a0a6ddc4b9f6dca050e3dacb3b39d8d54 901B / 901B                     0.0s
     => => sha256:82943290e75e46e5d4095862a63e45d942f12c738f7c984ac52b2a37b957004a 260.06MB / 260.06MB            10.3s
     => => sha256:9b74335bdc8ee94f816578ca3af04214fe9d024acba886fa62a0923a341b758c 741B / 741B                     0.0s
     => => sha256:769c82043b30e14fbd917b385c41170f9ca8ee1fd0c9d96c3bebc61a21f752bc 529B / 529B                     0.0s
     => => extracting sha256:82943290e75e46e5d4095862a63e45d942f12c738f7c984ac52b2a37b957004a                      6.5s
     => [internal] load build context                                                                              0.5s
     => => transferring context: 27.25MB                                                                           0.5s
     => [2/8] RUN pacman -Sy --noconfirm   cmake   arm-none-eabi-gcc   arm-none-eabi-newlib   ca-certificates    125.9s
     => [3/8] RUN git clone -b 1.4.0                                   4.0s  => [4/8] RUN cd /pico-sdk/lib && git submodule update --init ./                                              29.7s  => [5/8] WORKDIR /prk_firmware                                                                                0.0s  => [6/8] COPY . .                                                                                             0.3s  => ERROR [7/8] RUN rake setup                                                                                 1.4s ------                                                                                                               > [7/8] RUN rake setup:                                                                                            #12 1.420 rake aborted!                                                                                             #12 1.420 Don't know how to build task 'setup' (See the list of available tasks with `rake --tasks`)
    #12 1.422 
    #12 1.422 (See full trace by running task with --trace)
    executor failed running [/bin/sh -c rake setup]: exit code: 1
    ⏰182.82s total
    ~/prk/prk_firmware ❯❯❯                                                                               ✘ 1 master ✱ ◼
    opened by hidsh 1
  • Large Duplex Matrix causing rp2040 to crash

    Large Duplex Matrix causing rp2040 to crash

    I've noticed that when I do a large duplex matrix it crashes the RP2040 and the only way to get it to come back is to nuke the flash and put PRK back on it.

    Here is the keymap.rb that I used for testing just in case I did something wrong

    kbd =
    row0 = 1
    row1 = 2
    row2 = 3
    row3 = 4
    row4 = 5
    row5 = 6
    col0 = 7
    col1 = 8
    col2 = 9
    col3 = 10
    col4 = 11
    col5 = 12
    col6 = 13
    col7 = 14
    col8 = 16
    # Init duplex matrix
        [ [row0, col0], [col0, row0], [row0, col1], [col1, row0], [row0, col2], [col2, row0], [row0, col3], [col3, row0], [row0, col4], [col4, row0], [row0, col5], [col5, row0], [row0, col6], [col6, row0], [row0, col7], [col7, row0], [row0, col8], [col8, row0] ],
        [ [row1, col0], [col0, row1], [row1, col1], [col1, row1], [row1, col2], [col2, row1], [row1, col3], [col3, row1], [row1, col4], [col4, row1], [row1, col5], [col5, row1], [row1, col6], [col6, row1], [row1, col7], [col7, row1], [row1, col8], [col8, row1] ],
        [ [row2, col0], [col0, row2], [row2, col1], [col1, row2], [row2, col2], [col2, row2], [row2, col3], [col3, row2], [row2, col4], [col4, row2], [row2, col5], [col5, row2], [row2, col6], [col6, row2], [row2, col7], [col7, row2], [row2, col8], [col8, row2] ],
        [ [row3, col0], [col0, row3], [row3, col1], [col1, row3], [row3, col2], [col2, row3], [row3, col3], [col3, row3], [row3, col4], [col4, row3], [row3, col5], [col5, row3], [row3, col6], [col6, row3], [row3, col7], [col7, row3], [row3, col8], [col8, row3] ],
        [ [row4, col0], [col0, row4], [row4, col1], [col1, row4], [row4, col2], [col2, row4], [row4, col3], [col3, row4], [row4, col4], [col4, row4], [row4, col5], [col5, row4], [row4, col6], [col6, row4], [row4, col7], [col7, row4], [row4, col8], [col8, row4] ],
        [ [row5, col0], [col0, row5], [row5, col1], [col1, row5], [row5, col2], [col2, row5], [row5, col3], [col3, row5], [row5, col4], [col4, row5], [row5, col5], [col5, row5], [row5, col6], [col6, row5], [row5, col7], [col7, row5], [row5, col8], [col8, row5] ]
    kbd.add_layer :default, %i(
          KC_1          KC_2          KC_3          KC_4     KC_5 KC_6 KC_7 KC_8 KC_9 KC_0 KC_1 KC_2 KC_3 KC_4 KC_5 KC_6 KC_7 KC_8
          KC_1          KC_2          KC_3          KC_4     KC_5 KC_6 KC_7 KC_8 KC_9 KC_0 KC_1 KC_2 KC_3 KC_4 KC_5 KC_6 KC_7 KC_8
          KC_1          KC_2          KC_3          KC_4     KC_5 KC_6 KC_7 KC_8 KC_9 KC_0 KC_1 KC_2 KC_3 KC_4 KC_5 KC_6 KC_7 KC_8
          KC_1          KC_2          KC_3          KC_4     KC_5 KC_6 KC_7 KC_8 KC_9 KC_0 KC_1 KC_2 KC_3 KC_4 KC_5 KC_6 KC_7 KC_8
          KC_1          KC_2          KC_3          KC_4     KC_5 KC_6 KC_7 KC_8 KC_9 KC_0 KC_1 KC_2 KC_3 KC_4 KC_5 KC_6 KC_7 KC_8
          KC_1          KC_2          KC_3          KC_4     KC_5 KC_6 KC_7 KC_8 KC_9 KC_0 KC_1 KC_2 KC_3 KC_4 KC_5 KC_6 KC_7 KC_8
    opened by doesntfazer 5
  • [New feature] Auto copying keymap.rb to the partner half of the split-type

    [New feature] Auto copying keymap.rb to the partner half of the split-type


    • Split-type


    • Overwriting a keymap.rb happens on the anchor
    • Anchor pings a special signal to the partner in order to start copying the keymap.rb
    • Both halves switch into XMODEM (or something like that) mode
    • Anchor transfers the keymap.rb (or compiled VM code) to the partner
    • Partner saves the keymap.rb file in the flash
    • Partner sends a signal to finalize the flow
    • Both halves switch back to keyboard mode and reload the new keymap


    • Are there cases where a user wants to have a different keymap on the partner half?
    opened by hasumikin 0
  • Board not detected

    Board not detected

    My board is detected in BootSel mode. The PRKFirmware drive appears when I install the UF2 file... but once I unplug the board and plug it back in, nothing appears and the keyboard won't work.

    I have this issue with KMK as well. It was solved there by defining, then decreasing the startup delay multiplier. I set and adjusted this variable: PICO_XOSC_STARTUP_DELAY_MULTIPLIER. This value is set in a file called: pico-sdk-configboard.h

    To do this I had to create my own board within circuitPython and compile my own UF2 file.

    I think this all stems from some possible timing mismatches with the crystal on our board.

    Is there a way to deal with this in PRK please?

    opened by RonnyM82 1
  • Mode keys will run a proc placed in

    Mode keys will run a proc placed in "hold" no matter what the hold time is set to

    I wanted to make a key that presses backspace if tapped, and keypad enter if held for a while. This is what I ended up writing:

    kbd.define_mode_key :ENTER_DEL, [ :KC_BSPACE, { kbd.send_key(:KC_KP_ENTER); puts "Enter" }, 10000, nil]

    (the long time and the puts is just for testing) However, if I keep it pressed, "Enter" appears in the console several times.

    Now that I think about it, this might be intended behavior. If it is, I would like to request some way of doing what I want here; a key which does one key if tapped, and another if pressed for a while.

    opened by SekoiaTree 1
  • Request: Combos

    Request: Combos

    Combos are a popular feature in other keyboard firmwares like QMK and KMK which let you chord two keypresses together to perform an action. For example: press A and B together within a 50ms period and you will send C. If the timer times out, the user releases a combo key within its timeout, or the user presses another key that would not match with a chord, the original keypress will be sent instead. The timeout should be user-configurable to account for differences in dexterity, preferably defined individually for each combo.

    QMK page on combos KMK page on combos

    opened by Jawfish 0
A Ruby interpreter implementation for one-chip microcontrollers
A cross platform C99 library to get cpu features at runtime.

cpu_features A cross-platform C library to retrieve CPU features (such as available instructions) at runtime. Table of Contents Design Rationale Code

Google 2.2k Dec 22, 2022
A cross-platform protocol library to communicate with iOS devices

libimobiledevice A library to communicate with services on iOS devices using native protocols. Features libimobiledevice is a cross-platform software

libimobiledevice 5.4k Dec 30, 2022
Platform independent Near Field Communication (NFC) library

*- * Free/Libre Near Field Communication (NFC) library * * Libnfc historical contributors: * Copyright (C) 2009 Roel Verdult * Copyright (C) 2009

null 1.4k Jan 5, 2023
WAFer is a C language-based software platform for scalable server-side and networking applications. Think node.js for C programmers.

WAFer WAFer is a C language-based ultra-light scalable server-side web applications framework. Think node.js for C programmers. Because it's written i

Riolet Corporation 693 Dec 6, 2022
A cross-platform OpenXR capabilities explorer and runtime switcher with a CLI and GUI.

OpenXR Explorer OpenXR Explorer is a handy debug tool for OpenXR developers. It allows for easy switching between OpenXR runtimes, shows lists of the

Nick Klingensmith 154 Dec 13, 2022
LibOS is a modern C++17 library that makes OS-specific features cross-platform.

LibOS is a modern C++17 library that makes OS-specific features cross-platform. Ever tried to get Windows version after Windows 8? Or to send ke

Gavrilikhin Daniil 27 Sep 13, 2022
split89 keyboard - a 3d printed 89 key split TKL keyboard base powered by ATmega32U4 Pro Micro controllers with QMK Configurator support.

split89 keyboard - a 3d printed 89 key split TKL keyboard base powered by ATmega32U4 Pro Micro controllers with QMK Configurator support. This keyboar

null 54 Jan 7, 2023
Raw HID keyboard forwarder to turn the Pi 400 into a USB keyboard

Raspberry Pi 400 as a USB HID Keyboard Hook your Pi 400 up to your PC somehow, using a USB Type-C cable into the power port. Anker make good ones- I u

Philip Howard 182 Dec 12, 2022
Use Atari keyboard as USB keyboard with a Teensy 3.6

Atari Keyboard Convert an Atari 600/800/1200 XL into a USB keyboard. I bricked my Atari mainboard. My goal is to use the keyboard of the Atari on a Ra

Jos Koenis 2 Dec 3, 2021
Gesture-Detecting-Macro-Keyboard - Glorified Bluetooth macro keyboard with machine learning (TensorFlow Lite for Microcontrollers) running on an ESP32.

Gesture detection tldr; Glorified Bluetooth macro keyboard with machine learning (TensorFlow Lite for Microcontrollers) running on an ESP32. Main feat

Jakob Krantz 68 Dec 1, 2022
Simple ATTiny85 based PS/2 to Amiga keyboard protocol converter that fits inside the keyboard.

Simple ATTiny85 based PS/2 to Amiga keyboard protocol converter that fits inside the keyboard.

Jari Tulilahti 9 Dec 23, 2022
nrf52832 nrf52810 ble keyboard firmware

BLEKeyboard nrf52832 nrf52810 ble keyboard firmware WHY Learm more about hardware design and engineering. WHAT Implement a full featured powerful and

Jason Zhou 周正昌 42 Dec 1, 2022
YUIOP60Pi DIY Keyboard Firmware

YUIOP60Pi - DIY keyboard with PGA2040 firmware Requirements PICO SDK (v1.2.0) cmake compiler or so How to build $ make Output: build\yuiop60pi.uf2 Har

MURAOKA Taro 5 Aug 19, 2022
Devterm keyboard & trackball firmware

DevTerm Keyboard Firmware How to install Install Arduino STM32 hardware package on your Arduino IDE

SeongChan Lee 23 Dec 24, 2022
Cross-platform C++ input library supporting gamepads, keyboard, mouse, touch

This project is archived. It's neither maintained nor developed anymore. Gainput Gainput is the awesome C++ input library for your game: handles your

Johannes Kuhlmann 766 Jan 3, 2023
Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform.

Marlin 3D Printer Firmware Additional documentation can be found at the Marlin Home Page. Please test this firmware and let us know if it misbehaves i

Marlin 14.2k Jan 2, 2023
Three split ergo keyboard with macropad running QMK

IIICC Three piece split keyboard with macropad running QMK Features Split ergo Additional optional macropad with OLED and rotary encoder Central Hub d

null 32 Dec 21, 2022
ESP32 software USB host through general IO pins. We can connect up to 4 USB-LS HID (keyboard mouse joystick) devices simultaneously.

esp32_usb_soft_host esp32 USB-LS pure software host thru general IO pins. Up to 4 HID devices simultaneously. board ~$3 :

Samsonov Dima 313 Jan 1, 2023
Play GTA San Andreas Multiplayer with mouse only and no keyboard

Play GTA SAMP with your mouse and no keyboard! For some reason some people think it's a troll or an inside joke, IT IS NOT! This is a legit mod for th

iAmir 21 Aug 31, 2022
stacked acrylic gasket mounted ergonomic keyboard

Splay46 Build guide This keyboard requires soldering of really small smd components like USB Type C Receptacle(0.3mm pitch), Atmega32U4(0.8mm pitch),

kobakos 41 Jan 6, 2023