/*
NAME:                  4 Partial switches, 5 Position switches and 5 Octave switches, volume control, pitch bend and modulation control to MIDI Output 
 WRITTEN BY:           TOM SCARFF
 DATE:                 30/9/2009
 FILE SAVED AS:        midi_trombone.pde
 FOR:                  Miduino ATmega168
 CLOCK:                16.00 MHz CRYSTAL                                        
 PROGRAMME FUNCTION:   4 Partial switches, 5 Position switches and 5 Octave switches, volume control, pitch bend and modulation control representing trombone to MIDI 
 
 
 
 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 ON_Threshold 100  // Set noise threshold level before switching ON
#define OFF_Threshold 100 // Set LOW level to switch OFF
#define ON_Delay   10       // Set Delay after ON-Threshold is reached, to measure velocity (max volume) of note

//variables setup

byte DEBUG=0;

byte modulationLSB;
byte modulationMSB;
int modulationLevel;
int pitchBend;
int pitchLSB;
int pitchMSB;

int pressureSensor;
unsigned int switchCombination=0x0000;
byte n;
byte midiByte;
byte MIDIchannel=0;  // MIDI channel 1
byte velocity;
byte note;

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=0;
byte LedPin = 13;   // select the pin for the LED
byte runStatusFlag=0;
byte realTimeTest;
byte count;



void setup() {
  pinMode(2, INPUT); // Set Inputs 
  pinMode(3, INPUT); 
  pinMode(4, INPUT); 
  pinMode(5, INPUT); 
  pinMode(6, INPUT); 
  pinMode(7, INPUT); 
  pinMode(8, INPUT); 
  pinMode(9, INPUT); 
  pinMode(10, INPUT); 
  pinMode(11, INPUT); 
  pinMode(12, INPUT);  
  pinMode(17, INPUT); 
  pinMode(18, INPUT); 
  pinMode(19, INPUT);

  digitalWrite(2, HIGH); // Set inputs Pull-up resistors High
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH); 
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH); 
  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(12, HIGH);
  digitalWrite(17, HIGH);
  digitalWrite(18, HIGH);
  digitalWrite(19, 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);
  }

  if (DEBUG==1){
    Serial.begin(38400);  //start serial for screen printing
  }

  else if(DEBUG==0){
    Serial.begin(31250);  //start serial with midi baudrate 31250
  }
  Serial.flush();
}


void loop() {

  pressureSensor = analogRead(0);


  if(pressureSensor > ON_Threshold){
    delay(ON_Delay); // Delay X mS before measuring Velocity
    velocity = analogRead(0)/8;

    readSwitches();
    getNoteOn(switchCombination);

    do{
      pressureSensor = analogRead(0);
      velocity = pressureSensor/8;
      // include Volume Pitch Bend and Modulation
      pitch_bend();
      modulation();
    }
    while(pressureSensor > OFF_Threshold);

    if (Flag==1){
      midiSend((0x80 | MIDIchannel), note, velocity); // send Note Off command
      Flag=0;
    }

  }




}
//_______________________________________________________________________________________________

//  Send a three byte midi message  
void midiSend(byte status, byte data1, byte data2) {
  digitalWrite(LedPin,HIGH);  // indicate we're sending MIDI data
  Serial.print(status, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2 , BYTE);
  digitalWrite(LedPin,LOW);  // indicate we're sending MIDI data

  Flag=1;
}

//**************************************************************

void pitch_bend(){
  pitchBend = analogRead(2); // read voltage on analog pin A2
  pitchBend = map(pitchBend,0,1023,0,16383);
  pitchLSB = pitchBend & 0x007F;
  pitchMSB = (pitchBend >>7) & 0x007F;

  midiSend((0xE0 | MIDIchannel), pitchLSB, pitchMSB);
}

//***********************************************************

void modulation(){
  modulationLevel = analogRead(1); // read voltage on analog pin A1
  modulationLevel = map(modulationLevel,0,1023,0,16383);
  modulationLSB =  modulationLevel & 0x007F;
  modulationMSB = (modulationLevel >>7) & 0x007F;
  midiSend((0xB0 | MIDIchannel), 1, modulationLSB);
  midiSend((0xB0 | MIDIchannel), 33, modulationMSB);
}

//---------------------------------------------------------------------------------------------------
void readSwitches(){

  switchCombination=0x0000;

  // Read  switches 
  switchCombination=digitalRead(2) + (digitalRead(3)<<1) + (digitalRead(4)<<2) + (digitalRead(5)<<3)  + (digitalRead(6)<<4) + (digitalRead(7)<<5) + (digitalRead(8)<<6) + (digitalRead(9)<<7)+(digitalRead(10)<<8);


  //============================================================== 
  if(DEBUG){
    Serial.print("Switch: ");
    Serial.println(switchCombination, DEC);

    Serial.println(switchCombination, HEX);


  }
  //============================================================== 


}


//____________________________________________________________________________________________________

void getNoteOn(unsigned int var){

  //============================================================== 
  if(DEBUG){
    Serial.print(" GetNoteOn var: ");
    Serial.println(var, DEC);

    Serial.println(var, HEX);


  }
  //==============================================================

  switch (var) {


  case 0x00F7:
    note = 34;   //Bb
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);

    break;

  case 0x00FB:
    note = 38;  //D
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x00FD:
    note = 41;  //F
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x00FE:
    note = 44;  //Ab
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x0177:
    note = 33;  //A
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x017B:
    note = 37;  //Db
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x017D:
    note = 40;  //E
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x017E:
    note = 43;  //G
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01B7:
    note = 32;  //Ab
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01BB:
    note = 36;  //C
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01BD:
    note = 39;  //Eb
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01BE:
    note = 42;  //Gb
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01D7:
    note = 31;  //G
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01DB:
    note = 35;  //B
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01DD:
    note = 38;  //D
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01DE:
    note = 41;  //F
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01E7:
    note = 30;  //Gb
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01EB:
    note = 34;  //Bb
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01ED:
    note = 37;  //Db
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  case 0x01EE:
    note = 40;  //E
    getOctave();
    midiSend((0x90 | MIDIchannel), note, velocity);
    break;

  default:
    break;  

  }

}

//____________________________________________________________________________________________________

void getOctave(){

  if(digitalRead(11)==0){
    note=note+0;
  }
  if(digitalRead(12)==0){
    note=note+12;
  }
  if(digitalRead(17)==0){
    note=note+24;
  }
  if(digitalRead(18)==0){
    note=note+36;
  }
  if(digitalRead(19)==0){
    note=note+48;
  }


}



//---------------------------------------------------------------------------------------------------