#include <MozziGuts.h>
#include <Oscil.h>



#include <tables/saw256_int8.h>
#include <Adafruit_ADS1015.h>
#include <Wire.h>
//#include <mozzi_fixmath.h>
//#include <utility/twi_nonblock.h>

#define CONTROL_RATE 128 // powers of 2 please

Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_1(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_2(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_3(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_4(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_5(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_6(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_7(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_8(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_9(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_10(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_11(SAW256_DATA);
Oscil<SAW256_NUM_CELLS, AUDIO_RATE> tone_12(SAW256_DATA);

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

int count= 0;
int TH;
int16_t adc0a, adc1a, adc2a, adc3a, adc0b, adc1b, adc2b, adc3b, adc0c, adc1c, adc2c, adc3c, adc0d, adc1d, adc2d, adc3d;
boolean note1 = false;
boolean note2 = false;
boolean note3 = false;
boolean codeswitch = false;


void setup(){
      //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); 
      
      //start the multiplexing
      adsa.begin();
      adsb.begin();
      adsc.begin();
      adsd.begin();
      
      startMozzi(CONTROL_RATE);
    
      //set tone frequency and phase
      tone_1.setFreq(165);
      tone_1.setPhase(0);
      tone_2.setFreq(196);
      tone_2.setPhase(30);
      tone_3.setFreq(220);
      tone_3.setPhase(60);
      tone_4.setFreq(262);
      tone_4.setPhase(90);
      tone_5.setFreq(330);
      tone_5.setPhase(120);
      tone_6.setFreq(392);
      tone_6.setPhase(150);
      tone_7.setFreq(440);
      tone_7.setPhase(180);
      tone_8.setFreq(523);
      tone_8.setPhase(210);
      tone_9.setFreq(659);
      tone_9.setPhase(240);
      tone_10.setFreq(784);
      tone_10.setPhase(270);
      tone_11.setFreq(880);
      tone_11.setPhase(300);
      tone_12.setFreq(1047);
      tone_12.setPhase(330);
    
      //calibrate (set treshold)
      TH = adsb.readADC_SingleEnded(3);
}

void updateControl(){
    //log number of notes playing
    if (adc0a < TH) {
        count++;
    }
    if (adc1a < TH) {
        count++;
    }
    if (adc2a < TH) {
        count++;
    }
    if (adc3a < TH) {
        count++;
    }
    if (adc0b < TH) {
        count++;
    }
    if (adc1b < TH) {
        count++;
    }
    if (adc2b < TH) {
        count++;
    }
    if (adc3b < TH) {
        count++;
    }
    if (adc0c < TH) {
        count++;
    }
    if (adc1c < TH) {
        count++;
    }
    if (adc2c < TH) {
        count++;
    }
    if (adc3c < TH) {
        count++;
    }   
}


int updateAudio(){
    int result = 0;

    //Play notes and mix down (according to notes playing
    if (adc0a < TH) {
        result += tone_1.next() * (1/count);
    }
    if (adc1a < TH) {
        result += tone_2.next() * (1/count);
    }
    if (adc2a < TH) {
        result += tone_3.next() * (1/count);
    }
    if (adc3a < TH) {
        result += tone_4.next() * (1/count);
    }
    if (adc0b < TH) {
        result += tone_5.next() * (1/count);
    }
    if (adc1b < TH) {
        result += tone_6.next() * (1/count);
    }
    if (adc2b < TH) {
        result += tone_7.next() * (1/count);
    }
    if (adc3b < TH) {
        result += tone_8.next() * (1/count);
    }
    if (adc0c < TH) {
        result += tone_9.next() * (1/count);
    }
    if (adc1c < TH) {
        result += tone_10.next() * (1/count);
    }
    if (adc2c < TH) {
        result += tone_11.next() * (1/count);
    }
    if (adc3c < TH) {
        result += tone_12.next() * (1/count);
    }
    return result; 
}

void loop(){
    //Messure LDR multiplex inputs
    adc0a = adsa.readADC_SingleEnded(0);
    adc1a = adsa.readADC_SingleEnded(1);
    adc2a = adsa.readADC_SingleEnded(2);
    adc3a = adsa.readADC_SingleEnded(3);
  
    adc0b = adsb.readADC_SingleEnded(0);
    adc1b = adsb.readADC_SingleEnded(1);
    adc2b = adsb.readADC_SingleEnded(2);
    adc3b = adsb.readADC_SingleEnded(3);
  
    adc0c = adsc.readADC_SingleEnded(0);
    adc1c = adsc.readADC_SingleEnded(1);
    adc2c = adsc.readADC_SingleEnded(2);
    adc3c = adsc.readADC_SingleEnded(3);
  
    adc0d = adsd.readADC_SingleEnded(0);
    adc1d = adsd.readADC_SingleEnded(1);
    adc2d = adsd.readADC_SingleEnded(2);
    adc3d = adsd.readADC_SingleEnded(3);
  
    audioHook();
}
