/* 8 note MIDI sequencer */ /* Version 1.7 Sam Harmon 2008 */ /* http://www.glacialcommunications.com */ /* contains parts of... */ /* * codeexample for useing a 4051 * analog multiplexer / demultiplexer * by david c. and tomek n.* for k3 / malmš hšgskola * */ /* version 1.7 - Debut of "Drum Mode" - This enables the "Analog" sequencer to either do CV/Gate * (switch 4 set to 0) or triggering two drum sources (s4==1) * Drum mode triggering based on noteRead value - 0=no sound; 1-512, pin 5; 513-1022, pin 9; 1023, both */ //#define DEBUG 1 int r0 = 0; //value select pin at the 4051 (s0) int r1 = 0; //value select pin at the 4051 (s1) int r2 = 0; //value select pin at the 4051 (s2) int row = 0; // storeing the bin code int count = 0; // just a count int clockCount = 0; int bin [] = {000, 1, 10, 11, 100, 101, 110, 111};//bin = binŠr, some times it is so easy int tempoPin = 1; //pin for tempo read int tempoDelay = 0; //current amount to delay (aka tempo) int notePin = 0; //pin for reading current MIDI note int noteRead = 0; // int noteValue = 65; //MIDI note number //int noteDuration = 100; //length of note (for now) int velocity = 127; //MIDI velocity (default, for now) int fracDelay = 0; int modePin =4; //analog output - CV/Gate or 2-channel triggers int analogOut = 0; //value to send to CV out void setup(){ pinMode(6, OUTPUT); //s0 pinMode(7, OUTPUT); // s1 pinMode(8, OUTPUT); // s2 pinMode(9, OUTPUT); // PWM "CV" pinMode(5, OUTPUT); // "GATE" pinMode(modePin, INPUT); //mode switch CV/Gate or 2-channel drum machine // MIDI/CV switch //initialize CV/Gate analogWrite(9, 0); digitalWrite(5, LOW); #ifdef DEBUG beginSerial(9600); //debug #else Serial.begin(31250); #endif } void loop () { for (count=0; count<=7; count++) { tempoDelay = 1024-analogRead(tempoPin)+6; //in case sensor is zero, we want 1 ms delays noteRead = (analogRead(notePin)); //MIDI limited to 0-127 noteValue = noteRead/8; //PWM limited to 0-255 analogOut = noteRead/4; row = bin[count]; r0 = row & 0x01; r1 = (row>>1) & 0x01; r2 = (row>>2) & 0x01; digitalWrite(6, r0); digitalWrite(7, r1); digitalWrite(8, r2); #ifdef DEBUG Serial.print("modePin="); Serial.println(digitalRead(modePin)); #endif if (noteValue > 0){ noteOn(0x90, noteValue, velocity); if (digitalRead(modePin)==1){ //drum mode // evaluate note value // This is kind of ugly, anyone have a more elegant solution? if ((noteRead >0) && (noteRead < 512)){ digitalWrite(9, HIGH); } if ((noteRead > 512) && (noteRead < 1023)){ digitalWrite(5, HIGH); } if (noteRead==1023){ digitalWrite(5, HIGH); digitalWrite(9, HIGH); } //trigger pulse==10ms? delay(10); //go ahead and clear both digitalWrite(5,LOW); digitalWrite(9,LOW); } else { //standard mode digitalWrite(5, HIGH); analogWrite(9, analogOut); } } fracDelay = tempoDelay / 6; for (clockCount = 0; clockCount <=5;clockCount++){ syncSignal(0xF8); delay (fracDelay); } if (noteValue > 0){ noteOn(0x90,noteValue, 0x00); digitalWrite(5, LOW); analogWrite(9, 0); } } } void syncSignal(char cmd){ Serial.print(cmd, BYTE); } void noteOn(char cmd, char data1, char data2) { Serial.print(cmd, BYTE); Serial.print(data1, BYTE); Serial.print(data2, BYTE); }