/* NAME: MIDI Drums to 16 TTL Outputs WRITTEN BY: TOM SCARFF DATE: 12/1/2009 FILE SAVED AS: midi_drums_LEDS.pde FOR: Miduino ATmega168 CLOCK: 16.00 MHz CRYSTAL PROGRAMME FUNCTION: Detect midi Drum inputs and send 16 corresponding TTL outputs. IMPORTANT: The Miduino might not start if it receives data directly after a reset, because the bootloader thinks you want to upload a new progam.You might need to unplug the MIDI IN cable until the board is running your program. Also when programming the Miduino disconnect the MIDI IN cable. HARDWARE NOTE: The Midi IN Socket is connected to the Miduino RX through an 6N139 opto-isolator * * To send MIDI, attach a MIDI out Female 180 Degree 5-Pin DIN socket to Arduino. * Socket is seen from solder tags at rear. * DIN-5 pinout is: _______ * pin 2 - Gnd / \ * pin 4 - 220 ohm resistor to +5V | 1 3 | MIDI jack * pin 5 - Arduino Pin 1 (TX) via a 220 ohm resistor | 4 5 | * all other pins - unconnected \___2___/ * * ***************************************************************************** * */// define the output pins (anthonydp: i only use 10 outputs)#define Output0 2#define Output1 3#define Output2 4#define Output3 5#define Output4 6 #define Output5 7#define Output6 8#define Output7 9#define Output8 10#define Output9 11//#define Output10 12//variables setupbyte midiByte;byte MIDIchannel = 0; //drum channel (anthonydp: channel 1, but we'll use all channels and filter channel on PC side)byte channel;byte status=0;byte statusType;byte statusTest;byte volume_now=0;byte volume_past=0;byte x;byte startTest=0;byte runningStatus;byte Flag;byte LedPin = 13; // select the pin for the LEDbyte runStatusFlag=0;byte realTimeTest;byte count;byte note;byte startNoteFlag=0;int startNote=60;int channelTest=0;void setup() { pinMode(Output0,OUTPUT); pinMode(Output1,OUTPUT); pinMode(Output2,OUTPUT); pinMode(Output3,OUTPUT); pinMode(Output4,OUTPUT); pinMode(Output5,OUTPUT); pinMode(Output6,OUTPUT); pinMode(Output7,OUTPUT); pinMode(Output8,OUTPUT); pinMode(Output9,OUTPUT); pinMode(12, INPUT); // Program Switch digitalWrite(12, HIGH); // Set inputs Pull-up resistors High pinMode(LedPin,OUTPUT); // declare the LED's pin as output for (x=1; x<=4; x++){ digitalWrite( LedPin, HIGH ); delay(300); digitalWrite( LedPin, LOW ); delay(300); } Serial.begin(38400); //start serial with midi baudrate 38400 Roland MIDI //Serial.begin(31250); //start serial with midi baudrate 31250 Serial.flush();}void loop() { // Midi in to out midiThru();}//_____________________________________________________________________________________________________// Functions://++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void midiThru(){ if (Serial.available() > 0){ //If MIDI available read the incoming MIDI byte and transmit it thru midiByte = Serial.read(); digitalWrite(LedPin, HIGH); // sets the LED on statusType= midiByte&0xF0; statusTest=midiByte&0x80; channel=midiByte&0x0F; if(statusTest==0x80){ // if midi status and NOT data if(midiByte>=0x80 && midiByte<=0xEF){ //if midi channel command runningStatus=midiByte; } status=midiByte; Serial.print(status,BYTE); // transmit midi status byte txMidi(); // transmit following data bytes } if(statusTest!=0x80&&status!=0){ // if running status and NOT starting data byte status=runningStatus; // insert status byte channel=status&0x0F; statusType= status&0xF0; Serial.print(status,BYTE); // transmit midi running status byte txMidi2(status); // transmit following data bytes } } digitalWrite(LedPin, LOW); // sets the LED off} //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void readMidi(){ while (Flag==0){ if (Serial.available() > 0) { midiByte = Serial.read(); Flag=1; } } Flag=0;}////++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void txMidi(){ if(statusType==0xF0){ getStatus1(status); // complete status byte } else if(statusType!=0xF0){ getStatus2(status); // status with channel removed }}//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void getStatus1(byte val){ switch (val) { case 0xF0: //Begin System Exclusive 11110000 (F0) while (midiByte!=0XF7){ // until End of Sysex if (Serial.available() > 0) { midiByte = Serial.read(); Serial.print(midiByte,BYTE); } } break; case 0xF1: //MIDI Time Code 11110001 (F1) mididata1Tx(); break; case 0xF2: //Song Position Pointer 11110010 (F2) mididata2Tx(); break; case 0xF3: //Song Select 11110011 (F3) mididata1Tx(); break; case 0xF7: //End System Exclusive 11110111 (F7) break; // single byte data case 0xF8: //Timing Clock 11111000 (F8) // single byte data break; case 0xFA: //Start 11111010 (FA) // single byte data break; case 0xFB: //Continue 11111011 (FB) // single byte data break; case 0xFC: //Stop 11111100 (FC) // single byte data break; case 0xFE: //Active Sensing 11111110 (FE) // single byte data break; case 0xFF: //System Reset 11111111 (FF) // single byte data break; default: break; }}//___________________________________________________void getStatus2(byte val){ val = val & 0xF0; //remove channel info switch (val) { case 0x90: // Note-On Event 1001bbbb (9X) //mididata2Tx(); count=2; while (count!=0){ readMidi(); // get midi realTimeTest=midiByte&0x80; // if Real Time dont decrement count if (realTimeTest==0){ //if(count==2 && channel==MIDIchannel){ //anthonydp: commented this out so we'll allow all midi channels if(count==2){ //anthonydp: added this note=midiByte; } //else if (count==1 && channel==MIDIchannel){ //anthonydp: commented this out so we'll allow all midi channels else if (count==1){ if(midiByte==0){ getNoteOff(note); } else if(midiByte!=0){ getNoteOn(note); } } count=count-1; } // data byte Serial.print(midiByte,BYTE); // transmit midi } break; case 0x80: //Note-Off Event 1000bbbb (8X) //mididata2Tx(); count=2; while (count!=0){ readMidi(); // get midi realTimeTest=midiByte&0x80; // if Real Time dont decrement count if (realTimeTest==0){ //if (count==2 && channel==MIDIchannel){ //anthonydp: commented this out so we'll allow all midi channels if (count==2){ //anthonydp: added this getNoteOff(midiByte); } count=count-1; } // data byte Serial.print(midiByte,BYTE); // transmit midi } break; case 0xA0: //Control Polyphonic Key Pressure 1010bbbb (AX) 0kkkkkkk 0fffffff mididata2Tx(); break; case 0xB0: //Control Change 1011bbbb (BX) mididata2Tx(); break; case 0xC0: //Program Change 1100bbbb (CX) mididata1Tx(); break; case 0xD0: //Channel Pressure 1101bbbb (DX) mididata1Tx(); break; case 0xE0: //Pitch Bend 1110bbbb (EX) mididata2Tx(); break; default: break; }}////++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void txMidi2(byte val){ // running status mode data 1 available already in midiByte val = val & 0xF0; //remove channel info switch (val) { case 0x90: // Note-On Event 1001bbbb (9X) //if(channel==MIDIchannel) //anthonydp: commented this out so we'll allow all midi channels { note=midiByte; } Serial.print(midiByte,BYTE); // transmit midi data // mididata1Tx(); count=1; while (count!=0){ readMidi(); // get midi realTimeTest=midiByte&0x80; // if Real Time dont decrement count if (realTimeTest==0){ //if (count==1 && channel==MIDIchannel){ //anthonydp: commented this out so we'll allow all midi channels if (count==1){ if(midiByte==0){ getNoteOff(note); } if(midiByte!=0){ getNoteOn(note); } } count=count-1; } // data byte Serial.print(midiByte,BYTE); // transmit midi } break; case 0x80: //Note-Off Event 1000bbbb (8X) //if(channel==MIDIchannel) //anthonydp: commented this out so we'll allow all midi channels { getNoteOff(midiByte); } Serial.print(midiByte,BYTE); // transmit midi note data // mididata1Tx(); count=1; while (count!=0){ readMidi(); // get midi realTimeTest=midiByte&0x80; // if Real Time dont decrement count if (realTimeTest==0){ count=count-1; } Serial.print(midiByte,BYTE); // transmit midi } break; case 0xA0: //Control Polyphonic Key Pressure 1010bbbb (AX) 0kkkkkkk 0fffffff Serial.print(midiByte,BYTE); // transmit midi Polyphonic Key Pressure data 1 mididata1Tx(); break; case 0xB0: //Control Change 1011bbbb (BX) Serial.print(midiByte,BYTE); // transmit midi control data 1 mididata1Tx(); break; case 0xC0: //Program Change 1100bbbb (CX) Serial.print(midiByte,BYTE); // transmit midi program change data break; case 0xD0: //Channel Pressure 1101bbbb (DX) Serial.print(midiByte,BYTE); // transmit midi channel pressure data break; case 0xE0: //Pitch Bend 1110bbbb (EX) Serial.print(midiByte,BYTE); // transmit midi Pitch Bend data 1 mididata1Tx(); break; default: break; }}//---------------------------------------------------------------------------------void mididata2Tx(){ count=2; while (count!=0){ readMidi(); // get midi realTimeTest=midiByte&0x80; // if Real Time dont decrement count if (realTimeTest==0){ count=count-1; } // data byte Serial.print(midiByte,BYTE); // transmit midi }} //------------------------------------------------------------------------------void mididata1Tx(){ count=1; while (count!=0){ readMidi(); // get midi realTimeTest=midiByte&0x80; // if Real Time dont decrement count if (realTimeTest==0){ count=count-1; } // data byte Serial.print(midiByte,BYTE); // transmit midi }}////++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++////++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++void getNoteOn(byte var){ byte i = var % 10; digitalWrite(2 + i,HIGH); //anthonydp: we allow all notes on all octaves to be displayed on our 10 lights}//==========================================void getNoteOff(byte var){ byte i = var % 10; digitalWrite(2 + i,LOW); //anthonydp: we allow all notes on all octaves} //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++