#include <MozziGuts.h>
#include <Oscil.h>
#include <tables/sin2048_int8.h>
#include <Line.h> // for envelope
#include <ADSR.h>
#include <mozzi_fixmath.h>

#include <ADC.h>
#include <IntervalTimer.h>

//#include <MusicWithoutDelay.h>
//#include <synth.h>
//#include <tables.h>

#include <Wire.h>
#include <Adafruit_ADS1015.h>

//multiplexer adresses
Adafruit_ADS1115 adsa (0x48);
Adafruit_ADS1115 adsb (0x49);
Adafruit_ADS1115 adsc (0x4A);
Adafruit_ADS1115 adsd (0x4B);


//note values
//const char note0[] PROGMEM = ":d=128,b=300:c-1+";  //plays c4
//const char note1[] PROGMEM = ":d=128,b=300:d-1+";  //plays d4
//const char note2[] PROGMEM = ":d=128,b=300:e-1+";  //plays e4
//const char note3[] PROGMEM = ":d=128,b=300:g-1+";  //plays g4
//const char note4[] PROGMEM = ":d=128,b=300:a-1+";  //plays a4
//const char note5[] PROGMEM = ":d=128,b=300:c+";  //plays c5
//const char note6[] PROGMEM = ":d=128,b=300:d+";  //plays d5
//const char note7[] PROGMEM = ":d=128,b=300:e+";  //plays e5
//const char note8[] PROGMEM = ":d=128,b=300:g+";  //plays g5
//const char note9[] PROGMEM = ":d=128,b=300:a+";  //plays a5
//const char note10[] PROGMEM = ":d=128,b=300:c+1+";  //plays c6
//const char note11[] PROGMEM = ":d=128,b=300:d+1+";  //plays d6
//const char note12[] PROGMEM = ":d=128,b=300:e+1+";  //plays e6
//const char note13[] PROGMEM = ":d=128,b=300:g+1+";  //plays g6
//const char note14[] PROGMEM = ":d=128,b=300:a+1+";  //plays a6
//const char note15[] PROGMEM = ":d=128,b=300:c+2+";  //plays c7

//instruments
//MusicWithoutDelay Insta(note0);
//MusicWithoutDelay Instb(note1);
//MusicWithoutDelay Instc(note2);
//MusicWithoutDelay Instd(note3);
//MusicWithoutDelay Inste(note4);
//MusicWithoutDelay Instf(note5);
//MusicWithoutDelay Instg(note6);
//MusicWithoutDelay Insth(note7);
//MusicWithoutDelay Insti(note8);
//MusicWithoutDelay Instj(note9);
//MusicWithoutDelay Instk(note10);
//MusicWithoutDelay Instl(note11);
//MusicWithoutDelay Instm(note12);
//MusicWithoutDelay Instn(note13);
//MusicWithoutDelay Insto(note14);
//MusicWithoutDelay Instp(note15);

#define CONTROL_RATE 64
#define ATTACK 50 // long enough for control rate to catch it
#define DECAY 50
#define SUSTAIN 600000 // Sustain 60 seconds unless a noteOff comes.
#define RELEASE 1000
#define ATTACK_LEVEL 255
#define DECAY_LEVEL 255

Oscil <2048, AUDIO_RATE> Insta(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instb(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instc(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instd(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Inste(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instf(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instg(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Insth(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Insti(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instj(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instk(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instl(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instm(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instn(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Insto(SIN2048_DATA);
Oscil <2048, AUDIO_RATE> Instp(SIN2048_DATA);

ADSR <CONTROL_RATE, CONTROL_RATE> envelope1;

int count;
//int vol;
int VA0, VA1, VA2, VA3, VA4, VA5, VA6, VA7, VA8, VA9, VA10, VA11, VA12, VA13, VA14, VA15;
int TH0, TH1, TH2, TH3, TH4, TH5, TH6, TH7, TH8, TH9, TH10, TH11, TH12, TH13, TH14, TH15;
int VOL0, VOL1, VOL2, VOL3, VOL4, VOL5, VOL6, VOL7, VOL8, VOL9, VOL10, VOL11, VOL12, VOL13, VOL14, VOL15;
bool CV;

bool ZER;
bool ONE;
bool TWO;
bool THR;
bool FOU;
bool FIV;
bool SIX;
bool SEV;
bool EIG;
bool NIN;
bool TEN;
bool ELE;
bool TWE;
bool THT;
bool FOT;
bool FIT;

void setup() {
  Serial.begin(9600);

      //set the gain for multiplexed INs
    adsa.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
    adsb.setGain(GAIN_ONE); 
    adsc.setGain(GAIN_ONE); 
    adsd.setGain(GAIN_ONE); 

    Serial.println("Ini MPX ");
    adsa.begin();
    adsb.begin();
    adsc.begin();
    adsd.begin();
    Serial.println("MPX Ini");

  //calibrate the LDRs
  Serial.println ("Calib");
  TH0 = (adsa.readADC_SingleEnded(0) + 800);
  TH1 = (adsa.readADC_SingleEnded(1) + 800);
  TH2 = (adsa.readADC_SingleEnded(2) + 800);
  TH3 = (adsa.readADC_SingleEnded(3) + 800);
  TH4 = (adsb.readADC_SingleEnded(0) + 800);
  TH5 = (adsb.readADC_SingleEnded(1) + 800);
  TH6 = (adsb.readADC_SingleEnded(2) + 800);
  TH7 = (adsb.readADC_SingleEnded(3) + 800);
  TH8 = (adsc.readADC_SingleEnded(0) + 800);
  TH9 = (adsc.readADC_SingleEnded(1) + 800);
  TH10 = (adsc.readADC_SingleEnded(2) + 800);
  TH11 = (adsc.readADC_SingleEnded(3) + 800);
  TH12 = (adsd.readADC_SingleEnded(0) + 800);
  TH13 = (adsd.readADC_SingleEnded(1) + 800);
  TH14 = (adsd.readADC_SingleEnded(2) + 800);
  TH15 = (adsd.readADC_SingleEnded(3) + 800);

  Serial.print ("TH0=");
  Serial.println (TH0);
  Serial.print ("TH1=");
  Serial.println (TH1);
  Serial.print ("TH2=");
  Serial.println (TH2);
  Serial.print ("TH3=");
  Serial.println (TH3);
  Serial.print ("TH4=");
  Serial.println (TH4);
  Serial.print ("TH5=");
  Serial.println (TH5);
  Serial.print ("TH6=");
  Serial.println (TH6);
  Serial.print ("TH7=");
  Serial.println (TH7);
  Serial.print ("TH8=");
  Serial.println (TH8);
  Serial.print ("TH9=");
  Serial.println (TH9);
  Serial.print ("TH10=");
  Serial.println (TH10);
  Serial.print ("TH11=");
  Serial.println (TH11);
  Serial.print ("TH12=");
  Serial.println (TH12);
  Serial.print ("TH13=");
  Serial.println (TH13);
  Serial.print ("TH14=");
  Serial.println (TH14);
  Serial.print ("TH15=");
  Serial.println (TH15);

  Serial.println("Wait4MWD");
  Serial.println("Ini MWD");


  Insta.setFreq(165);
  Insta.setPhase(0);
  Instb.setFreq(196);
  Instb.setPhase(30);
  Instc.setFreq(220);
  Instc.setPhase(60);
  Instd.setFreq(262);
  Instd.setPhase(90);
  Inste.setFreq(330);
  Inste.setPhase(120);
  Instf.setFreq(392);
  Instf.setPhase(150);
  Instg.setFreq(440);
  Instg.setPhase(180);
  Insth.setFreq(523);
  Insth.setPhase(210);
  Insti.setFreq(659);
  Insti.setPhase(240);
  Instj.setFreq(784);
  Instj.setPhase(270);
  Instk.setFreq(880);
  Instk.setPhase(300);
  Instl.setFreq(1047);
  Instl.setPhase(330);
  Instm.setFreq(659);
  Instm.setPhase(240);
  Instn.setFreq(784);
  Instn.setPhase(270);
  Insto.setFreq(880);
  Insto.setPhase(300);
  Instp.setFreq(1047);
  Instp.setPhase(330);

  envelope1.setADLevels(ATTACK_LEVEL,DECAY_LEVEL);
  envelope1.setTimes(ATTACK,DECAY,SUSTAIN,RELEASE);
//
//  Insta.begin(CHA, TRIANGLE, ENVELOPE2, 0);
//  Instb.begin(TRIANGLE, ENVELOPE2, 0);
//  Instc.begin(TRIANGLE, ENVELOPE2, 0);
//  Instd.begin(TRIANGLE, ENVELOPE2, 0);
//  Inste.begin(TRIANGLE, ENVELOPE2, 0);
//  Instf.begin(TRIANGLE, ENVELOPE2, 0);
//  Instg.begin(TRIANGLE, ENVELOPE2, 0);
//  Insth.begin(TRIANGLE, ENVELOPE2, 0);
//  Insti.begin(TRIANGLE, ENVELOPE2, 0);
//  Instj.begin(TRIANGLE, ENVELOPE2, 0);
//  Instk.begin(TRIANGLE, ENVELOPE2, 0);
//  Instl.begin(TRIANGLE, ENVELOPE2, 0);
//  Instm.begin(TRIANGLE, ENVELOPE2, 0);
//  Instn.begin(TRIANGLE, ENVELOPE2, 0);
//  Insto.begin(TRIANGLE, ENVELOPE2, 0);
//  Instp.begin(TRIANGLE, ENVELOPE2, 0);
//
//  Insta.pause(true);
//  Instb.pause(true);
//  Instc.pause(true);
//  Instd.pause(true);
//  Inste.pause(true);
//  Instf.pause(true);
//  Instg.pause(true);
//  Insth.pause(true);
//  Insti.pause(true);
//  Instj.pause(true);
//  Instk.pause(true);
//  Instl.pause(true);
//  Instm.pause(true);
//  Instn.pause(true);
//  Insto.pause(true);
//  Instp.pause(true);

  startMozzi(CONTROL_RATE);

  Serial.println("go!");
}

void updateControl(){
  if (VA0 > TH0) {
    count++;
    ZER = true;
    if (CV) {
      digitalWrite(0, HIGH);
    }
    else if (!CV) {
      digitalWrite(0, LOW);
    }
  }
  else if (VA0 < TH0) {
    ZER = false;
    //Kill ControlVoltage
    digitalWrite(0, LOW);
  }
    
  if (VA1 > TH1) {
    count++;
    ONE = true;
    if (CV) {
      digitalWrite(1, HIGH);
    }
    else if (!CV) {
      digitalWrite(1, LOW);
    }
  }
  else if (VA1 < TH1) {
    ONE = false;
    //Kill ControlVoltage
    digitalWrite(1, LOW);
  }
  
  if (VA2 > TH2) {
    count++;
    TWO = true;
    if (CV) {
      digitalWrite(2, HIGH);
    }
    else if (!CV) {
      digitalWrite(2, LOW);
    }
  }
  else if (VA2 < TH2) {
    TWO = false;
    //Kill ControlVoltage
    digitalWrite(2, LOW);
  }

  if (VA3 > TH3) {
    count++;
    THR = true;
    if (CV) {
      digitalWrite(3, HIGH);
    }
    else if (!CV) {
      digitalWrite(3, LOW);
    }
  }
  else if (VA3 < TH3) {
    THR = false;
    //Kill ControlVoltage
    digitalWrite(3, LOW);
  }

  if (VA4 > TH4) {
    count++;
    FOU = true;
        if (CV) {
      digitalWrite(4, HIGH);
    }
    else if (!CV) {
      digitalWrite(4, LOW);
    }
  }
  else if (VA4 < TH4) {
    FOU = false;
    //Kill ControlVoltage
    digitalWrite(4, LOW);
  }

  if (VA5 > TH5) {
    if (CV) {
      digitalWrite(5, HIGH);
    }
    else if (!CV) {
      digitalWrite(5, LOW);
    }
    count++;
    FIV = true;
  }
  else if (VA5 < TH5) {
    FIV = false;
    //Kill ControlVoltage
    digitalWrite(5, LOW);
  }

  if (VA6 > TH6) {
    count++;
    SIX = true;
    if (CV) {
      digitalWrite(6, HIGH);
    }
    else if (!CV) {
      digitalWrite(6, LOW);
    }
  }
  else if (VA6 < TH6) {
    SIX = false;
    //Kill ControlVoltage
    digitalWrite(6, LOW);
  }

  if (VA7 > TH7) {
    count++;
    SEV = true;
    if (CV) {
      digitalWrite(7, HIGH);
    }
    else if (!CV) {
      digitalWrite(7, LOW);
    }
  }
  else if (VA7 < TH7) {
    SEV = false;
    //Kill ControlVoltage
    digitalWrite(7, LOW);
  }

  if (VA8 > TH8) {
    count++;
    EIG = true;
    if (CV) {
      digitalWrite(8, HIGH);
    }
    else if (!CV) {
      digitalWrite(8, LOW);
    }
  }
  else if (VA8 < TH8) {
    EIG = false;
    //Kill ControlVoltage
    digitalWrite(8, LOW);
    
  }

  if (VA9 > TH9) {
    count++;
    NIN = true;
    if (CV) {
      digitalWrite(9, HIGH);
    }
    else if (!CV) {
      digitalWrite(9, LOW);
    }
  }
  else if (VA9 < TH9) {
    NIN = false;
    //Kill ControlVoltage
    digitalWrite(9, LOW);
  }
  
  if (VA10 > TH10) {
    count++;
    TEN = true;
    if (CV) {
      digitalWrite(10, HIGH);
    }
    else if (!CV) {
      digitalWrite(10, LOW);
    }
  }
  else if (VA10 < TH10) {
    TEN = false;
    //Kill ControlVoltage
    digitalWrite(10, LOW);
  }

  if (VA11 > TH11) {
    count++;
    ELE = true;
    if (CV) {
      digitalWrite(11, HIGH);
    }
    else if (!CV) {
      digitalWrite(11, LOW);
    }
  }
  else if (VA11 < TH11) {
    ELE = false;
    //Kill ControlVoltage
    digitalWrite(11, LOW);
  }

  if (VA12 > TH12) {
    count++;
    TWE = true;
    if (CV) {
      digitalWrite(12, HIGH);
    }
    else if (!CV) {
      digitalWrite(12, LOW);
    }
  }
  else if (VA12 < TH12) {
    TWE = false;
    //Kill ControlVoltage
    digitalWrite(12, LOW);
  }

  if (VA13 > TH13) {
    count++;
    THT = true;
    if (CV) {
      digitalWrite(13, HIGH);
    }
    else if (!CV) {
      digitalWrite(13, LOW);
    }
  }
  else if (VA13 < TH13) {
    THT = false;
    //Kill ControlVoltage
    digitalWrite(13, LOW);
  }

  if (VA14 > TH14) {
    count++;
    FOT = true;
    if (CV) {
      digitalWrite(14, HIGH);
    }
    else if (!CV) {
      digitalWrite(14, LOW);
    }
  }
  else if (VA14 < TH14) {
    FOT = false;
    //Kill ControlVoltage
    digitalWrite(14, LOW);
  }

  if (VA15 > TH15) {
    count++;
    FIT = true;
    if (CV) {
      digitalWrite(15, HIGH);
    }
    else if (!CV) {
      digitalWrite(15, LOW);
    }
  }
  else if (VA15 < TH15) {
    FIT = false;
    //Kill ControlVoltage
    digitalWrite(15, LOW);
  }


//  Serial.print("Intruments playing = ");
//  Serial.println(count);
}

int updateAudio(){
      int result = 0;
    //Play notes and mix down (set volume depending on number of notes playing)
  if (ZER) {
  //envelope1.update();
  //return Insta.noteOn());
  return (Insta) (envelope1.noteOn());
  }

  if (!ZER) {
    envelope1.noteOff();
  }

  if (ONE) {
//    VOL1 = 50/count+constrain(map(VA1, TH1, TH1+5000, 0, 65), 0, 65);
  result += Instb.next();
  }

  if (!ONE) {
  }

  if (TWO) {
  result += Instc.next();
  }

  if (!TWO) {
  }

  if (THR) {
  result += Instd.next();
  }

  if (!THR) {
  }

  if (FOU) {
  result += Inste.next();
  }

  if (!FOU) {
  }

  if (FIV) {
  result += Instf.next();
  }

  if (!FIV) {
  }

  if (SIX) {
  result += Instg.next();
  }

  if (!SIX) {
  }

  if (SEV) {
  result += Insth.next();
  }

  if (!SEV) {
  }


  if (EIG) {
  result += Insti.next();
  }

  if (!EIG) {
  }

  if (NIN) {
  result += Instj.next();
  }

  if (!NIN) {
  }

    if (TEN) {
  result += Instk.next();
  }

  if (!TEN) {
  }

      if (ELE) {
  result += Instl.next();
  }

  if (!ELE) {
  }
  
    if (TWE) {
  result += Instm.next();
  }

  if (!TWE) {
  }
    
    if (THT) {
  result += Instn.next();
  }

  if (!THT) {
  }
      
    if (FOT) {
  result += Insto.next();
  }

  if (!FOT) {
  }

        
    if (FIT) {
  result += Instp.next();
  }

  if (!FIT) {
  }
  return;
}

void loop() {
  CV = digitalRead(22);
  count = 0;

//  Insta.update();
//  Instb.update();
//  Instc.update();
//  Instd.update();
//  Inste.update();
//  Instf.update();
//  Instg.update();
//  Insth.update();
//  Insti.update();
//  Instj.update();
//  Instk.update();
//  Instl.update();
//  Instm.update();
//  Instn.update();
//  Insto.update();
//  Instp.update();

  //Messure LDR inputs
  VA0 = adsa.readADC_SingleEnded(0);
  VA1 = adsa.readADC_SingleEnded(1);
  VA2 = adsa.readADC_SingleEnded(2);
  VA3 = adsa.readADC_SingleEnded(3);
  
//      Serial.print("VA0: "); Serial.println(VA0);
//      Serial.print("VA1: "); Serial.println(VA1);
//      Serial.print("VA2: "); Serial.println(VA2);
//      Serial.print("VA3: "); Serial.println(VA3);
//      Serial.println(" ");

  VA4 = adsb.readADC_SingleEnded(0);
  VA5 = adsb.readADC_SingleEnded(1);
  VA6 = adsb.readADC_SingleEnded(2);
  VA7 = adsb.readADC_SingleEnded(3);
  
//      Serial.print("VA4: "); Serial.println(VA4);
//      Serial.print("VA5: "); Serial.println(VA5);
//      Serial.print("VA6: "); Serial.println(VA6);
//      Serial.print("VA7: "); Serial.println(VA7);
//      Serial.println(" ");

  VA8 = adsc.readADC_SingleEnded(0);
  VA9 = adsc.readADC_SingleEnded(1);
  VA10 = adsc.readADC_SingleEnded(2);
  VA11 = adsc.readADC_SingleEnded(3);

//      Serial.print("VA8: "); Serial.println(VA8);
//      Serial.print("VA9: "); Serial.println(VA9);
//      Serial.print("VA10: "); Serial.println(VA10);
//      Serial.print("VA11: "); Serial.println(VA11);
//      Serial.println(" ");

  VA12 = adsd.readADC_SingleEnded(0);
  VA13 = adsd.readADC_SingleEnded(1);
  VA14 = adsd.readADC_SingleEnded(2);
  VA15 = adsd.readADC_SingleEnded(3);

//      Serial.print("VA12: "); Serial.println(VA12);
//      Serial.print("VA13: "); Serial.println(VA13);
//      Serial.print("VA14: "); Serial.println(VA14);
//      Serial.print("VA15: "); Serial.println(VA15);
//      Serial.println(" ");

  
audioHook();
}
