VS1053 + Matrix keypad


The VS1053b is a popular chip, used in many MCU controlled audio projects. It surprises me that nobody seems to use its eight GPIO pins, controllable over SPI by the master MCU. These GPIO pins enabled me to control my esp8266 based Internet radio by means of a matrix keypad, despite the fact that the esp8266 had only one free pin left.

The cheap 12-key membrane keypad shown in the picure uses 7 of these pins, wheras a 16-key matrix keypad uses all of them.


Adafruit’s VS1053 library has basic functions for adressing the chip’s GPIO pins. I wrote a simple demo sketch that prints the pressed key. In a real project, this information would typically be used to control other functions of the VS1053, like changing audio source or adjusting volume.


Make sure that pin definitions in the demo sketch match your MCU and connect RST to your board’s RST.

The VS1053_GPIO wiring for the demo sketch is different from what the picture shows. This is what I used for my 12-key membrane matrix keypad:






The connector’s column/row mapping for these particular keypads is usually as follows (from left to right in the picture): row0 – row1 – row2 -row3 – col0 – col1 – col2. The sketch can easily be adapted for a 16-key matrix keypad.

The basic idea of the sketch is:

  • keypadListen() sets all four row pins to INPUT with value 0; it sets all three column pins to OUTPUT with value 1. In this idle state, GPIO_digitalRead() will return B00000111 (decimal 7).
  • In loop(), we check GPIO_digitalRead(). A value higher than 7 means that one of the row pins has changed from 0 to 1 because it got connected to one of the column pins. This happens if a key on that row was pressed (that’s how matrix keypads are wired). We call keypadRead() to find the responsible key.
  • keypadRead() searches the row that caused the GPIO_digitalRead() > 7 condition, by checking each row pin until it reads 1. This gives us the row of the pressed key: R.
  • Next, it finds the column pin that is connected to row pin R by setting all column pins to INPUT with value 0 and row pin R only to OUTPUT with value 1. Checking each column pin until it reads 1 gives the column of the pressed key: C.
  • Now, keymap[R][C] holds the value of the pressed key (10 and 11 for * and #).
  • A simple debouncer is added for, well, debouncing.