//           __  __ _____ _____ _____    _____            _             _ _                     //
//          |  \/  |_   _|  __ \_   _|  / ____|          | |           | | |                    //
//          | \  / | | | | |  | || |   | |     ___  _ __ | |_ _ __ ___ | | | ___ _ __           //
//          | |\/| | | | | |  | || |   | |    / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__|          //
//          | |  | |_| |_| |__| || |_  | |___| (_) | | | | |_| | | (_) | | |  __/ |             //
//          |_|  |_|_____|_____/_____|  \_____\___/|_| |_|\__|_|  \___/|_|_|\___|_|             //
//        yt.com/technikblock               bit.ly/technikblock                 technikblock.de //
                                                                          


//Potis und Fader                                        //Arrays (0 bis 6 zählen)
int potipin[] =             {A0,A1,A2,A3,A4,A5};         //Analoge Inputs 
int controllernote[] =      { 1, 3, 2, 5, 6, 4};         //MIDI Note
int controllerwert[]=       {0 ,0 ,0 ,0 ,0 , 0};         //MIDI Wert
int controllerwertalt[]=    {0 ,0 ,0 ,0 ,0 , 0};         //alter MIDI Wert
int potiwert[]=             {0 ,0 ,0 ,0 ,0 , 0};         //Potiwert
int smoothpoti[]=           {0 ,0 ,0 ,0 ,0 , 0};         //Potiwert geglättet


//Buttons                                                //Arrays (von 0 bis 6 zählen)
int button[] =      {LOW,LOW,LOW,LOW,LOW,                //Buttondruck
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW};  
                                                            
int buttonalt[] =   {LOW,LOW,LOW,LOW,LOW,                //alter Buttondruck
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW,LOW,LOW,
                     LOW,LOW,LOW};      
                             
int buttonpin[] =   { 4, 8, 7,53,51,49,47,               //Digitale Inputs
                     23,27,31,37,44,42,46,
                     50,24,26,32,36,45,43,
                     41,39,35,33,29,25,52,
                     48,40,38,34,30,28,22,
                     6, 5, 9};             
                              
int midinote[] =    {57,58,59,60,61,62,63,               //MIDI Noten
                     64,65,66,67,68,69,70,  
                     71,72,73,74,75,76,77,
                     78,79,80,81,82,83,84,
                     85,86,87,88,89,90,91,
                     92,93,94};                     

long lastdebouncetime = 0;                               //letztes mal als der Knopf getoggelt wurde
                             
long debouncedelay = 40;                                 //Debounce Zeit Standard: 50

int midinoteon = 144;                                    //Status-Byte (144 = Note On)
int midicontrolchange = 176;                             //Status-Byte (176 = Control Change)
int i = 0;                                               //Variable zum schreiben und lesen der Menge


void setup() {                                           //Setup
Serial.begin(9600);                                      //serielle Beginn und Geschwindigkeit (seriell: 9600, MIDI: 31250)
for (i = 0; i < 37; i++) {                               //38 Buttons
  pinMode(buttonpin[i], INPUT_PULLUP);                   //definiert digitalen Pin als Input mit Pullup Resistor
  }
}



void loop() {                                                     //Loop
 
 //Potis und Fader
    for (i = 0; i < 6; i++) {                                     //6 Potis
    potiwert[i] = analogRead(potipin[i]);                         //ließt Analoge Pins
    smoothpoti[i]= (6 * smoothpoti[i] + 4 * potiwert[i])/10;      //0,6 vom geglätteten Poti + 0,4 vom alten Poti (Gleitkommazahl-Berechnung vermieden)
    controllerwert[i] = map(smoothpoti[i],0,1023,0,127);          //umrechnen von alter Skala(0-1023) zu neuer Skala(0-127)

      if (controllerwert[i] != controllerwertalt[i]) {            //Wenn der Controllerwert nicht gleich (!=) controllerwertalt ist, dann:
      Serial.write(midicontrolchange);                            //schreibe MIDI Kanal
      Serial.write(controllernote[i]);                            //schreibe MIDI Note
      Serial.write(controllerwert[i]);                            //schreibe MIDI Wert
      controllerwertalt[i] = controllerwert[i];                   //alten mit neuem controllerwert vergleichen
      }
   }

 
 
 //Buttons
    for (i = 0; i < 38; i++) {                                    //38 Buttons
    button[i] = digitalRead(buttonpin[i]);}                       //ließt Digitale Pins
      
        lastdebouncetime = millis();                           
        for (i = 0; i < 38; i++) {
        
           if (button[i] == HIGH && buttonalt[i] == LOW) {        //Wenn Button hoch, dann schreibe:   
           Serial.write(midinoteon);                              //schreibe MIDI Kanal
           Serial.write(midinote[i]);                             //MIDI Note (24 = C1)
           Serial.write(0);                                       //MIDI Velocity (0 = 0%)
           buttonalt[i] = button[i];
           }
           if (button[i] == LOW && buttonalt[i] == HIGH) {        //Wenn Button tief, dann schreibe:  
           Serial.write(midinoteon);                              //schreibe MIDI Kanal
           Serial.write(midinote[i]);                             //MIDI Note (24 = C1)
           Serial.write(127);                                     //MIDI Velocity (127 = 100%)
           buttonalt[i] = button[i];                   
           } 
           }
           while ((millis() - lastdebouncetime) < debouncedelay){
          //do nothing
          }
      
   
}


//          Midi Syntax
//
//          Status-Byte          Data-Byte          Data-Byte
//          Art, Kanal           Note               Velocity
//          1 011 0000           0 1101010          0 0101111
//      
//          Status-Byte:
//          1 000 Note off
//          1 001 Note on (144)
//          1 010 Poly Presure
//          1 011 Control Change (176)
//          1 100 Program Change
//          1 101 Channel Aftertouch
//          1 110 Pitch Bend
//
//          Data-Bytes jeweils 0-127 dezimal
//
//          binär -> dezimal