Parts: 4×4 RGB button pad controller SPI


We covered SparkFun’s new RGB button pad controller a few weeks ago. This is a full-color clone of the monome interface; a 4×4 grid of buttons with tri-color LEDs underneath. Each LED has 24bits of color control, for more than 16million color combinations. Up to 10 panels can be chained together to create huge button grids, like SparkFun’s Tetris table. We previously used a smaller version in our RGB combination lock.

We asked SparkFun to send us the SPI version of the button controller to test. This is a new product developed in-house at SparkFun, with open source hardware and software. Read about our experience interfacing this board below.

4×4 RGB button pad controller SPI (SparkFun #WIG-09022, $39.95)

The button pad controller is a bare PCB, we also received a button pad cover (SparkFun #COM-07835, $9.95), and two of each bezel (SparkFun #COM-08747, #COM-08746, $3.95).  The SPI version we’re working with can be driven directly by a microcontroller, or by a USB ‘master’. The USB controller version has an additional microcontroller and FTDI USB->serial converter for PC connectivity.

When the button pad arrived, we immediately sat down with the datasheet and tried to interface the board with our Bus Pirate universal serial interface. The protocol described in version 1 of the datasheet didn’t work, at all.

SparkFun open sourced this project, so we determined the correct interface protocol from the source code for the button pad SPI (ZIP) and the button pad USB controller (ZIP). We figured out most of the protocol from the source, but it still took help from SparkFun’s engineers to uncover some of the undocumented, finer points of interfacing the board. Version 2 of the datasheet (PDF) accurately depicts the interface protocol.


Bus Pirate Button pad
Clock SCK
+5volts VCC

The button pad’s SPI signals are described as they relate to the on-board microcontroller, which is opposite the usual notation. The MOSI (master out, slave in) signal is actually the board’s data output, and MISO (master in, slave out) is the data input.

We tested the button pad with the Bus Pirate, but the same basic principals apply to any custom microcontroller code. The board runs at 5volts, so we powered it from the Bus Pirate’s on-board 5volt power supply. The SPI interface operates at 5volt logic levels, so we connected the Bus Pirate’s pull-up resistors to the 5volt power supply and enabled them on all signal lines.

We interfaced the button board using the Bus Pirate’s raw3wire library. Raw3wire is a software SPI library with bit-wise operations. The hardware SPI library only allows full byte operations which aren’t granular enough to interface the board. We put the Bus Pirate in raw3wire mode (menu option M), and chose the HiZ pin option because the pull-up resistors will hold the bus at 5volts.

RAW3WIRE>l <–configure bit order
1. MSB first
2. LSB first
MODE>2 <–least significant bit first
RAW3WIRE>W <–enable power supply

The button pad communicates least significant bit first, so we also configured the library to communicate LSB first. Finally, we hit capital ‘W’ to enable the Bus Pirate’s power supplies. The button board will flash each color momentarily as part of its power-on self-test.

Single/multiple button board setup


Each board needs to be configured for single or multi-board use. Boards come pre-programmed for single-board operation, but it might be a good idea to set the configuration anyways. The board configuration is permanently stored in EEPROM, so it only has to be done once.

RAW3WIRE>[\_ <–take all signals low
CS ENABLED <–CS enabled is 0volts

A special sequence places the board in configuration mode. Begin with all signal lines low (]\_).

RAW3WIRE>-^ 1 1 <–set single board operation
DATA OUTPUT, 1 <–data high
0×01 CLOCK TICKS <–one clock tick
WRITE: 0×01 <–config option 1, number of boards
WRITE: 0×01 <–set the number of boards
RAW3WIRE>w <–small ‘w’, power off
RAW3WIRE>W <–capital ‘W’, power on

To enter configuration mode, take the data line high (-) and send one clock pulse (^), but leave chip select low. The board is now ready to accept configuration settings.

The first byte sent after entering configuration mode tells the board which setting to modify. Currently, only the number of boards can be configured (0×01). Next, send the number of connected boards, between 1 and 10. we sent 1 because we’re interfacing a single board. Reset the board and it will light a LED corresponding to the programmed number of boards.

Set colors and read button status

Now we’re ready to send color data to the board and read the button status. First, note that the CS (chip select) signal is opposite normal conventions. Usually CS activates a chip when the signal is low (0volts), and idles it when the signal is high (5volts); this is usually denoted by /CS, #CS, or !CS. Instead, the button controller is active when CS is high.


A 64byte transaction sets the LED colors and retrieves the button status. The first 16bytes program the red level for each LED, followed by 16bytes of green, and 16bytes of blue. Finish by reading 16bytes from the board to get the status of each button. Buttons data is sent as 0×00 if pressed, and 0xff if not pressed. The datasheet recommends a 400us delay between writing the color frames and reading the button data, but the Bus Pirate is slow enough that we won’t worry about that.


The protocol is simple enough, but there’s one major catch. The clock line must be high before raising CS, or the bytestream will be off by 1 bit. For this reason, many hardware SPI modules won’t work with the board.  This isn’t a problem if your microcontroller lets you twiddle pins that are controlled by a hardware module, but the micros we’ve worked with don’t allow this.


RAW3WIRE>/]255:16 255:16 255:16 r:16[
CLOCK, 1 <–clock must be high prior to raising CS
CS DISABLED <–CS to 5volts, opposite normal use
BULK WRITE 0xFF , 0x10 TIMES <–red LEDs
BULK WRITE 0xFF , 0x10 TIMES <–green LEDs
BULK WRITE 0xFF , 0x10 TIMES <–blue LEDs
BULK READ 0x10 BYTES: <–read button state
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
CS ENABLED <–CS to 0volts, opposite normal use

This command sets every color of each LED to full, and reads back the 16 button status bytes.

We first set clock high (/), and only then can we raise CS to 5volts (]) and begin the data transaction. 255:16 is a repeated command that sends the value 255  sixteen times. As each color channel has 8bits of intensity control, 255 is 100% on. We send 255 a total of 48 times, once for each color of each LED. Finally, we retrieve one 16byte frame of button data (r:16) and lower CS to end the transaction ([). The button values are all 0xff, indicating that no buttons are pressed.


RAW3WIRE>/] 0:16 0:16 128:16 r:16[
BULK WRITE 0x00 , 0x10 TIMES
BULK WRITE 0x00 , 0x10 TIMES
BULK WRITE 0x80 , 0x10 TIMES <–all blue to 50%
0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF

Here, we set the blue level of every LED to 50% (128) and turn off all other colors. The button output now shows that button 0 is pressed.


RAW3WIRE>/] 0 0 0 0 255 255 255 255 0 0 0 0 0 0 0 0 0:16 0:16 r:16[
WRITE: 0×00 <– red LED 0, off
<–more of the same
WRITE: 0×00 <– red LED 3, off
WRITE: 0xFF <– red LED 4, 100% on
WRITE: 0xFF <– red LED 5, 100% on
WRITE: 0xFF <– red LED 6, 100% on
WRITE: 0xFF <– red LED 7, 100% on
WRITE: 0×00 <– red LED 8, off
<–more of the same
WRITE: 0×00 <– red LED 15, off
BULK WRITE 0×00 , 0×10 TIMES <– all green LEDs off
BULK WRITE 0×00 , 0×10 TIMES <–all blue LEDs off
BULK READ 0×10 BYTES: <–read button status
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF

This example shows how to address single LEDs. This time we actually write out all 16 bytes of the red color frame. Buttons 0-3 and 8-15 have a red value of 0 (red off), buttons 4-7 are set to 100% red (255). All green and blue LEDs are off (0, 0%).


It was really frustrating to get this board working because the first version of the datasheet had so many errors. SparkFun’s engineers and support were really helpful, and posted a corrected datasheet within days. As long as you have the updated datasheet, this is an easy board to work with.

We’d like to see a firmware update that eliminates the need to keep the clock signal high before raising CS. This quirk makes the board incompatible with many hardware SPI modules, leaving slow bit-bang routines as the only interface option. Fortunately, the source code is open and available to anyone who wants to make this change.

The button pad controller is a really neat board, and we look forward to using it in a future project.

Hack a Day review disclosure: We asked for a free board and SparkFun sent it to us. We had a terrible time getting it to work with the instructions in the first version of the datasheet, we documented that experience here.

Comments are closed.