By popular request, here’s an update to the first code for the Button Pad Controller SPI. This sketch now includes interactive feedback, in the form of changing colours based on key-presses.
// The wires
#define CS 10
#define MISO 11
#define MOSI 12
#define SCK 13
// Frame buffer for lights
int lights = 16;
int depth = 3;
byte buf[16][3];
boolean wait = false;
boolean ready = true;
void setup() {
pinMode(CS, OUTPUT);
pinMode(MISO, OUTPUT);
pinMode(MOSI, INPUT);
pinMode(SCK, OUTPUT);
digitalWrite(CS, LOW);
delay(100);
blank();
Serial.begin(9600);
Serial.println("Starting");
}
void blank() {
// init frame buffer
for(int l = 0; l < lights; l++) {
for(int d = 0; d < depth; d++) {
buf[l][d] = 0;
}
}
}
void loop() {
digitalWrite(SCK, HIGH);
digitalWrite(CS, HIGH);
delayMicroseconds(15);
// Set lights: 3 x 16 bytes
for(int d = 0; d < depth; d++) {
for(int l = 0; l < lights; l++) {
writeByte(buf[l][d]);
}
}
if(!ready) {
wait = true;
ready = true;
}
// Read the buttons: 16 bytes.
for(int l = 0; l < lights; l++) {
// readByte returns a non-zero value when a button is pressed.
byte b = readByte();
// If a button is pressed, change the colour.
if (b > 0 && ready && !wait) {
if (buf[l][2] > 0) { buf[l][2] = 0; }
else if (buf[l][1] > 0) { buf[l][1] = 0; buf[l][2] = 255; }
else if (buf[l][0] > 0) { buf[l][0] = 0; buf[l][1] = 255; }
else { buf[l][0] = 255; }
Serial.print("Button ");
Serial.print(l);
Serial.print(": ");
Serial.print((int)b);
Serial.println();
// Change colours slowly.
ready = false;
}
}
digitalWrite(CS, LOW);
// After the second cycle, get ready to read new button clicks.
if(wait) {
delay(500);
wait = false;
ready = true;
}
delayMicroseconds(400);
}
// Write out a byte.
// This is for a single colour channel, for a single button.
void writeByte(byte data) {
for(int i = 0; i < 8; i++) {
digitalWrite(SCK, LOW);
delayMicroseconds(5);
digitalWrite(MISO, (data & (1 << i)) >> i);
delayMicroseconds(5);
digitalWrite(SCK, HIGH);
delayMicroseconds(10);
}
}
// Read a byte.
// Returns the value for a single button.
// Non-zero if it is pressed, or 0 otherwise.
byte readByte() {
byte result = 0;
for(int i = 0; i < 8; i++) {
digitalWrite(SCK, LOW);
delayMicroseconds(5);
result += (!digitalRead(MOSI)) * i;
delayMicroseconds(5);
digitalWrite(SCK, HIGH);
delayMicroseconds(10);
}
return result;
}




