A Matrix Keypad on a Raspberry Pi done right

There are quite a few articles to be found on the Internet on how to use a matrix keyboard on a Raspberry Pi.

Surprisingly none of them seems to use the method documented here.

Instead most of them seem to use some handcrafted Raspberry Pi and python-only solution with debounce logic implemented in userland.

As with my article on Setting up a GPIO-Button “keyboard” on a Raspberry Pi this uses a device tree based approach and will not require any driver code in userland.

As with the solution above an application will be able to use this keyboard just in the same way as any other keyboard (e.g. a standard USB keyboard) connected to a computer running Linux.

So here is how to do it:

Unfortunately, at the time of writing, the standard kernel of Raspbian does not include the required driver. I already filed a bug on GitHub, so this might change in future.

For now we need to build our own kernel.

To build the required driver module call make menuconfig after make XXXXXX_defconfig and enable CONFIG_KEYBOARD_MATRIX


After booting this kernel modinfo matrix-keypad should show you something like this:

pi@raspberrypi:~$ sudo modinfo matrix-keypad
alias:          platform:matrix-keypad
license:        GPL v2
description:    GPIO Driven Matrix Keypad Driver
author:         Marek Vasut 
srcversion:     54E6656500995BD553F6CA4
alias:          of:N*T*Cgpio-matrix-keypadC*
alias:          of:N*T*Cgpio-matrix-keypad
depends:        matrix-keymap
intree:         Y
vermagic:       4.9.35+ mod_unload modversions ARMv6 p2v8 

To enable the driver we need to create a device tree overlay file suitable for a given matrix keyboard.

As an example I use the following device available at your favorite china shop.


Here is what the corresponding device tree overlay file 4x5matrix.dts looks like:

    / {
           compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

           fragment@0 {
              target-path = "/";
              __overlay__ {
                 keypad: MATRIX4x5 {
                    compatible = "gpio-matrix-keypad";
                    debounce-delay-ms = <10>;
                    col-scan-delay-us = <10>;
		       try to use GPIO only lines
                       to keep SPI and I2C usable
                    row-gpios = <&gpio 27 0    // 1
                                 &gpio 22 0    // 2
                                 &gpio 10 0    // 3
                                 &gpio 9 0>;   // 4

                    col-gpios = <&gpio 13 0    // 5
                                 &gpio 26 0    // 6
                                 &gpio 16 0    // 7
                                 &gpio 20 0    // 8
                                 &gpio 21 0>;  // 9
                      Keycodes from /usr/include/linux/input-event-codes.h
                      converted to hex using printf '%02x\n'

                    linux,keymap = <
                                    // col0 row0 KEY_LEFT
                                    // col0 row1 KEY_KP0
                                    // col0 row2 KEY_RIGHT
                                    // col0 row3 KEY_KPENTER
				    // col1 row0 KEY_KP7
                                    // col1 row1 KEY_KP8
                                    // col1 row2 KEY_KP9
                                    // col1 row3 KEY_ESC
                                    // col2 row0 KEY_KP4
                                    // col2 row1 KEY_KP5
                                    // col2 row2 KEY_KP6
                                    // col2 row3 KEY_DOWN
                                    // col3 row0 KEY_KP1
                                    // col3 row1 KEY_KP2
                                    // col3 row2 KEY_KP3
                                    // col3 row3 KEY_UP
                                    // col4 row0 KEY_F1
                                    // col4 row1 KEY_F2
                                    // col4 row2 KEY_KPSLASH there is no KP_#
                                    // col4 row3 KEY_KPASTERISK


Further documentation can be found in the file Documentation/devicetree/bindings/input/matrix-keymap.txt inside the Linux kernel source tree. Feel free to ask if it does not work for you.

Now to enable our keyboard there are only four steps left:

  1. Connect the keyboard to the GPIO lines as defined in the dts file
  2. Compile the dts file to the binary dtbo format. This is done using the device tree compiler of your kernel tree:
    ./scripts/dtc/dtc -W no-unit_address_vs_reg -I dts -O dtb -o 4x5matrix.dtbo 4x5matrix.dts
  3. Copy the resulting dtbo file to /boot/overlays/4x5matrix.dtbo on the Raspberry Pi
  4. Add the following to /boot/config.txt:

Now after rebooting the Pi the lsinput command should show us a new keyboard connected to the device. You may need to install a package called input-utils first if this command ist not available on your Pi.

Here is what this looks like after pressing the Enter Key on the matrix keyboard:

pi@raspberrypi:~$ sudo -s
root@raspberrypi:~# lsinput
   bustype : BUS_HOST
   vendor  : 0x0
   product : 0x0
   version : 0
   name    : "MATRIX4x5"
   bits ev : EV_SYN EV_KEY EV_MSC EV_REP

root@raspberrypi:~# input-events 0
   bustype : BUS_HOST
   vendor  : 0x0
   product : 0x0
   version : 0
   name    : "MATRIX4x5"
   bits ev : EV_SYN EV_KEY EV_MSC EV_REP

waiting for events
19:56:28.727096: EV_MSC MSC_SCAN 24
19:56:28.727096: EV_KEY KEY_KPENTER (0x60) pressed
19:56:28.727096: EV_SYN code=0 value=0
19:56:28.797104: EV_MSC MSC_SCAN 24
19:56:28.797104: EV_KEY KEY_KPENTER (0x60) released
19:56:28.797104: EV_SYN code=0 value=0

Happy hacking!

Leave a Reply

Your email address will not be published. Required fields are marked *