
Demo video:
http://youtube.com/watch?v=I7CMI_imM68Today i have made a physical interface for the Arduino drum samples (as seen in a
previous post). Two 8-way DIP switches control the beat, a pot controls the sampling rate (and therefore pitch) and another pot controls the time between notes.
The two dip switches work in tandem so that each 1/8th note can have four possibilities (two bits) worth). If the position on the right switch is 0 and the position on the left switch is 0, then nothing is played. If the setup is 1 and 0, then a kick sample is played. If the setup is 0 and 1, then a snare sample is played. If the setup is 1 and 1, then a hi-hat sample is played.
So, for example, the following setup:
___SWITCH__LEFT___ ___SWITCH__RIGHT__
|0 0 1 0 1 0 1 0 | |1 0 1 0 0 0 1 0 |
------------------ ------------------
would give the following drum pattern:
KICK, TACET, HI-HAT, TACET, SNARE, TACET, HI-HAT, TACET
(because on the first 1/8th, the left switch is set to 0 and the right switch is set to 1 etc).
The two DIP switches are connected to the Arduino using 2 x 4021 shift registers. The sketch uses the a modified version of the code found in the ShiftIn tutorial by Carolyn Maw and Tom Igoe. The sound is output via an 8 bit R2R DAC. In fact, I seem to be using these quite a bit so I made myself a semi-hardwired one this morning. This is the board that is connected to PORTD (digital pins 0 - 7) on the Arduino. This is so much easier to deal with than scrounging around for suitable resistor values all the time, and then having to place them on the board.
Additionally, 2 LEDs keep track of timing -- one lights up on every 1/4 beat, and the other lights up at the start of every bar.

Schematic
Notes:
• PORTD pins 1 - 8 refers to digital pins 0 to 7
• PORTB pins 1 - 6 refers to digital pins 8 - 13
• PORTC pins 1 - 6 refers to analog pins 0 - 5
Arduino Code
/* Arduino Drum Machine
by Sebastian Tomczak
13 April 2008
*/
// 4021 Pins
int latchPin = 9;
int dataPin = 10;
int clockPin = 8;
// Working Variables
int delayTime;
byte dipSwitch1;
byte dipSwitch2;
byte beatByte;
int LED1 = 11;
int LED2 = 12;
int LED1_start = 0;
int LED1_end = 7;
// Samples
byte kick[] =
{
127, 80, 42, 5, 165, 242, 241, 233, 128, 73, 48, 22, 127, 69, 55, 113, 151, 183, 209, 217, 223, 228, 233, 215, 161, 117, 91, 76, 65, 49, 37, 31, 31, 48, 83, 120, 146, 166, 183, 198, 206, 210, 209, 199, 178, 145, 111, 88, 78, 73, 69, 67, 72, 80, 88, 97, 109, 124, 137, 150, 163, 171, 174, 172, 168, 160, 144, 125, 114, 110, 108, 104, 104, 106, 109, 110, 112, 117, 124, 129, 135, 142, 145, 145, 143, 140, 137, 132, 128, 125, 122, 119, 118, 119, 119, 119, 118, 118, 120, 124, 126, 129, 132, 135, 137, 137, 135, 132, 131, 130, 129, 128, 126, 126, 124, 123, 121, 120, 120, 122, 123, 124, 126, 128, 129, 130, 130, 131, 131, 131, 130, 130, 130, 129, 129, 128, 126, 125, 125, 124, 124, 124, 124, 125, 126, 126, 128, 128, 128, 129, 129, 129, 129, 129, 128, 128, 128, 128, 126, 126, 126, 126, 126, 126, 126, 126, 126, 128, 127, 126, 128, 128, 128, 128, 128, 128, 128, 128, 126, 126, 126, 126, 126, 126, 126, 126, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126
};
byte snare[] =
{
127, 215, 65, 212, 56, 102, 135, 122, 51, 201, 220, 46, 175, 80, 152, 95, 123, 116, 184, 155, 59, 122, 100, 161, 143, 173, 101, 155, 97, 73, 112, 98, 176, 96, 140, 77, 134, 109, 132, 149, 112, 149, 97, 161, 98, 151, 98, 155, 149, 112, 157, 103, 133, 106, 167, 97, 166, 108, 129, 124, 136, 146, 124, 136, 129, 150, 94, 130, 105, 141, 146, 128, 129, 99, 150, 121, 141, 99, 142, 116, 131, 114, 118, 143, 127, 143, 115, 144, 120, 137, 109, 129, 131, 139, 129, 113, 144, 119, 145, 117, 135, 129, 134, 136, 124, 130, 130, 139, 121, 136, 121, 132, 128, 127, 126, 122, 130, 126, 138, 120, 136, 122, 131, 123, 130, 128, 127, 128, 118, 132, 125, 131, 122, 131, 125, 131, 122, 126, 128, 126, 129, 121, 129, 123, 132, 129, 127, 131, 123, 128, 125, 130, 123, 131, 123, 128, 131, 129, 128, 126, 125, 124, 131, 121, 124, 129, 130, 126, 124, 126, 127, 130, 125, 126, 128, 126, 128, 126, 126, 126, 126, 125, 128, 126, 126, 126, 126, 126, 126, 125, 128, 126, 126, 126, 126, 126, 126, 126, 126, 128, 128, 126, 128, 126, 127, 126, 128, 125, 127, 128, 128, 126, 126, 128, 126, 126, 128, 128, 128, 128, 128, 126, 128, 126, 126, 128, 128, 126, 126, 128, 128, 126, 126, 127, 126, 128, 126, 126, 128, 128, 128, 126, 126, 126, 128, 128, 126, 126, 126, 128, 128, 126, 128, 128, 126, 126
};
byte hat[] =
{
127, 128, 225, 217, 99, 38, 61, 153, 152, 144, 133, 73, 122, 144, 65, 188, 87, 170, 164, 111, 122, 151, 114, 88, 174, 77, 140, 92, 122, 141, 156, 124, 121, 123, 126, 133, 132, 139, 119, 120, 127, 141, 130, 122, 129, 127, 132, 121, 139, 118, 130, 131, 129, 132, 130, 134, 126, 128, 130, 126, 122, 132, 129, 127, 131, 126, 128, 127, 126, 125, 127, 125, 128, 125, 128, 128, 127, 127, 126, 127, 128, 128, 128, 127, 127, 127, 127, 127, 128, 127, 127, 126, 127, 127, 128, 127, 128, 126, 127, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 128, 126, 126, 128, 127, 126, 127, 126, 127, 127, 126, 127, 126, 127, 127, 127, 127, 127, 126, 127, 127, 127, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 127, 127, 127, 126, 127, 127, 127, 126, 127, 127, 126, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 127, 127, 126, 127, 126, 126, 127, 126, 127, 126, 126, 126, 126, 126, 126, 126, 127, 127, 126, 127, 127, 127, 127, 126, 126, 127, 127, 127, 126, 127, 126, 127, 127, 127, 127, 127, 126, 126, 127, 127, 126, 127, 127, 127, 127, 126, 127, 127, 127, 127, 127, 127, 127, 127
};
byte crash[] =
{
127, 128, 225, 217, 99, 38, 61, 153, 152, 144, 133, 73, 122, 144, 65, 188, 87, 170, 164, 111, 122, 151, 114, 88, 174, 77, 140, 92, 122, 141, 156, 124, 121, 123, 126, 133, 132, 139, 119, 120, 127, 141, 130, 122, 129, 127, 132, 121, 139, 118, 130, 131, 129, 132, 130, 134, 126, 128, 130, 126, 122, 132, 129, 127, 131, 126, 128, 127, 126, 125, 127, 125, 128, 125, 128, 128, 127, 127, 126, 127, 128, 128, 128, 127, 127, 127, 127, 127, 128, 127, 127, 126, 127, 127, 128, 127, 128, 126, 127, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 128, 128, 126, 126, 128, 127, 126, 127, 126, 127, 127, 126, 127, 126, 127, 127, 127, 127, 127, 126, 127, 127, 127, 126, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 126, 126, 126, 127, 127, 127, 126, 127, 127, 127, 126, 127, 127, 126, 127, 127, 127, 127, 127, 127, 126, 126, 126, 126, 126, 126, 126, 127, 127, 126, 127, 126, 126, 127, 126, 127, 126, 126, 126, 126, 126, 126, 126, 127, 127, 126, 127, 127, 127, 127, 126, 126, 127, 127, 127, 126, 127, 126, 127, 127, 127, 127, 127, 126, 126, 127, 127, 126, 127, 127, 127, 127, 126, 127, 127, 127, 127, 127, 127, 127, 127
};
void setup() {
DDRD = B00000000;
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2,OUTPUT);
}
void loop() {
for(int j = 7; j >= 0; j --) {
if(j == LED1_start) {
digitalWrite(LED1, 1);
}
if(j == LED1_end)
{
digitalWrite(LED1, 0);
}
digitalWrite(LED2, 1 - (j % 2));
digitalWrite(latchPin, 1);
delayMicroseconds(20);
digitalWrite(latchPin, 0);
dipSwitch1 = shiftIn(dataPin, clockPin);
dipSwitch2 = shiftIn(dataPin, clockPin);
dipSwitch1 = (dipSwitch1 >> j) & B00000001;
dipSwitch2 = (dipSwitch2 >> j) & B00000001;
beatByte = dipSwitch1 | (dipSwitch2 << 1);
delayTime = analogRead(1) + 1;
playBeat(beatByte);
}
}
// Playback Functions
void playBeat(byte beat) {
if(beat == 0) {
for(int i = 0; i < 256; i ++) {
delayMicroseconds(analogRead(0) + 1);
}
}
else if(beat == 1) {
playKick();
}
else if(beat == 2) {
playSnare();
}
else if(beat == 3) {
playHat();
}
else if(beat == 4) {
playCrash();
}
delay(delayTime);
}
void playKick() {
for(int i = 0; i < 256; i ++) {
PORTD = kick[i];
delayMicroseconds(analogRead(0) + 1);
}
PORTD = 127;
}
void playSnare() {
for(int i = 0; i < 256; i ++) {
PORTD = snare[i];
delayMicroseconds(analogRead(0) + 1);
}
PORTD = 127;
}
void playHat() {
for(int i = 0; i < 256; i ++) {
PORTD = hat[i];
delayMicroseconds(analogRead(0) + 1);
}
PORTD = 127;
}
void playCrash() {
for(int i = 0; i < 256; i ++) {
PORTD = crash[i];
delayMicroseconds(analogRead(0) + 1);
}
PORTD = 127;
}
byte shiftIn(int myDataPin, int myClockPin) {
int i;
int temp = 0;
int pinState;
byte myDataIn = 0;
for (i=7; i>=0; i--)
{
digitalWrite(myClockPin, 0);
delayMicroseconds(2);
temp = digitalRead(myDataPin);
if (temp) {
pinState = 1;
myDataIn = myDataIn | (1 << i);
}
else {
pinState = 0;
}
digitalWrite(myClockPin, 1);
}
return myDataIn;
}