// Manual control of the Button Pad Controller SPI. // Based on documentation at // http://www.sparkfun.com/datasheets/Widgets/ButtonPadControllerSPI_UserGuide_v2.pdf // // By H.R.B.M., 2011. // 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; }