//declare variables
char ADC_turn=0;
signed int POT_trigger=32767;
unsigned int POT_granularity=6;
unsigned int POT_pitch;
unsigned int POT_window;
unsigned int POT_window_sampling;
unsigned int POT_fade;
unsigned int POT_fade_2;

signed int adc_value;
unsigned int count=0;
char buffer;
char audio_sens;
signed int audio_sample[8000];
signed long int audio_sample_long;
signed int audio_sample_last;
signed int audio_sample_difference;
unsigned int audio_sample_rotate;
unsigned int count1=0;
char sample_enabled=0;

unsigned int count_pitch=0;
unsigned int PR1_limit;

sbit Chip_Select_DAC at LATD10_bit;
sbit Chip_Select_ADC at LATE2_bit;
sbit LED at LATF0_bit;

sbit TOGGLE_octave at RD5_bit;
sbit TOGGLE_infinite at RD4_bit;

//initialize on-chip ADC
void InitADC(unsigned char ADC_channel) {
  static unsigned int WhichBit = 1;
  DisableInterrupts();
  WhichBit = (WhichBit << ADC_channel);
  TRISB |= WhichBit;
  AD1PCFG = ~WhichBit;
  AD1CON1bits.SSRC = 7;
  AD1CON1bits.FORM = 0;
  AD1CON1bits.ASAM = 0;
  AD1CHS = 0;
  AD1CHSbits.CH0SA = ADC_channel;
  AD1CSSL = 0;
  AD1CON3bits.ADRC = 0;
  AD1CON3bits.SAMC = 0x03;
  AD1CON3bits.ADCS = 0x02;
  AD1CON2 = 0;
  AD1CON1bits.ON = 1;
  EnableInterrupts();
 }

//sample on-chip ADC
unsigned int GetADC(void) {
  DisableInterrupts();
  AD1CON1bits.SAMP = 1;
  while(!AD1CON1bits.DONE);
  return(ADC1BUF0);
  EnableInterrupts();
 }

//sample audio from external ADC
void ADC_Input() {
     DisableInterrupts();
     Chip_Select_ADC = 0;
     adc_value = SPI2_Read(buffer);
     Chip_Select_ADC = 1;
     adc_value = adc_value << 3;
     adc_value = adc_value - 32768;
     adc_value = adc_value + 200;     //0 bias
     EnableInterrupts();
}

//output audio to external DAC
void DAC_Output(unsigned int valueDAC) {
     DisableInterrupts();
     valueDAC = valueDAC + 32768;
     valueDAC.F15 =~ valueDAC.F15;
     Chip_Select_DAC = 0;
     SPI3_Write(valueDAC);
     Chip_Select_DAC = 1;
     EnableInterrupts();
}

//####################################################################################################################################################################
//22KHz timer ~ do everything in here 22,000 times a second (usually)

void Sampling_loop() iv IVT_TIMER_1 ilevel 7 ics ICS_SRS {
     DisableInterrupts();
     T1IF_bit = 0;             // reset timer
     
     ADC_Input();

     //determine if audio should go forward or backward
      if (audio_sens == 1) {
         if (count1 < POT_window_sampling) {
            count1++;
         } else {
            audio_sens = 0;
            POT_fade_2 = POT_fade;
         }
     } else {
         if (count1 > 0) {
            count1--;
         } else {
            audio_sens = 1;
            POT_fade_2 = POT_fade;
         }
     }

     if (sample_enabled == 1) {
       audio_sample[count1] = adc_value;
       POT_window_sampling = (POT_window + 30);
     } else {
       POT_window_sampling = POT_window;
     }

     //simple fade algorithm
     audio_sample_long = audio_sample[count1];
     audio_sample_long = (audio_sample_long << 8);
     audio_sample_long = (audio_sample_long / POT_fade_2);
     audio_sample[count1] = audio_sample_long;

     audio_sample_last = audio_sample[count1];

     DAC_Output(audio_sample[count1]);

     //pitch bend
     if (TOGGLE_octave == 0 && sample_enabled == 0) {
        if (PR1 < PR1_limit && POT_pitch < 490) {
           if (count_pitch >= POT_pitch) {
              PR1++;
              count_pitch = 0;
              } else {
              count_pitch++;
              }
        }
     } else if (TOGGLE_octave == 1 && sample_enabled == 0) {
        if (PR1 > 454 && POT_pitch < 490) {
           if (count_pitch >= POT_pitch) {
              PR1--;
              count_pitch = 0;
              } else {
              count_pitch++;
              }
        }
     }

  EnableInterrupts();
}

//####################################################################################################################################################################
//do everything in here 100 or so times a second

void UI_Functions() iv IVT_TIMER_2 ilevel 7 ics ICS_SRS {
     DisableInterrupts();
     T2IF_bit = 0;             // reset timer

//rediculous ADC turn thing to compensate for ADC slowness
if (ADC_turn == 0) {
   InitADC(0);
} else if (ADC_turn == 1) {
   InitADC(1);
} else if (ADC_turn == 2) {
   InitADC(4);
} else if (ADC_turn == 3) {
   InitADC(5);
} else if (ADC_turn == 4) {
   InitADC(9);
}

if (ADC_turn == 2) {
     POT_trigger = GetADC(void);
     POT_trigger = POT_trigger << 5;
} else if (ADC_turn == 3) {
     POT_granularity = GetADC(void);
     POT_granularity = POT_granularity / 9; //3
     POT_granularity = POT_granularity + 6;
} else if (ADC_turn == 4) {
     POT_window = GetADC(void);
     POT_window = (POT_window * 7);
     POT_window = (POT_window + 800);
} else if (ADC_turn == 0) {
     POT_pitch = GetADC(void);
     POT_pitch = POT_pitch >> 1;
} else if (ADC_turn == 1) {
     POT_fade = GetADC(void);
     POT_fade = (POT_fade + 256);
}

if (ADC_turn == 4) {
     ADC_turn = 0;
   } else {
     ADC_turn++;
}

if (adc_value > POT_trigger && sample_enabled == 0) {
    if (count == 0) {
       count = 1;
    }
}

//do stuff
if (count > 0) {
   count++;
   if (count == 4) {
      LED = 1;
      PR1 = 1816;
      count_pitch = 0;
      sample_enabled = 1;
    } else if (count >= POT_granularity) {
      if (adc_value <= POT_trigger) {
         sample_enabled = 0;
         LED = 0;
         count = 0;
      } else {
         count = 4;
      }
    }
}

if (TOGGLE_infinite == 1) {
   PR1_limit = 58112;
} else {
   PR1_limit = 3632;
}

  EnableInterrupts();
}

 //####################################################################################################################################################################

void main() {
  SPI2_Init_Advanced(_SPI_MASTER, _SPI_16_BIT, 16, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);
  SPI3_Init_Advanced(_SPI_MASTER, _SPI_16_BIT, 2, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

  DDPCONbits.JTAGEN = 0;
  AD1PCFG = 0xFDCC;
  //AD1PCFG = 1111111111001100;
  
  TRISB0_bit = 1; //pot ADC as input
  TRISD10_bit = 0; //DAC CS as output
  TRISE2_bit = 0; //ADC CS as output
  TRISF0_bit = 0; //test LED
  Chip_Select_DAC = 1;
  Chip_Select_ADC = 1;
  LED = 0;
  TRISE7_bit = 1; //octave toggle as input
  TRISE6_bit = 1; //infinite toggle as input
  
  sample_enabled = 0;
  audio_sens = 1;

 //####################################################################################################################################################################

ON__T1CON_bit = 0;        // disable Timer1
  TMR1 = 0;                 // reset timer value to zero
  PR1 = 1816;              // Load period register
  T1IP0_bit = 1;            // set interrupt
  T1IP1_bit = 1;            // priority
  T1IP2_bit = 1;            // to 7
  TCKPS0_bit = 0;           // Set Timer Input Clock
  TCKPS1_bit = 0;           // Prescale value to 1:1
  T1IE_bit = 1;             // Enable Timer1 Interrupt
  ON__T1CON_bit = 1;        // Enable Timer1

//1ms timer

ON__T2CON_bit = 0;        // disable Timer2
  TMR2 = 0;                 // reset timer value to zero
  PR2 = 640;              // Load period register
  T2IP0_bit = 1;            // set interrupt
  T2IP1_bit = 1;            // priority
  T2IP2_bit = 1;            // to 7
  TCKPS0_T2CON_bit = 1;           // Set Timer Input Clock
  TCKPS1_T2CON_bit = 1;           // Prescale value to 1:256
  TCKPS2_bit = 1;
  T2IE_bit = 1;             // Enable Timer2 Interrupt
  ON__T2CON_bit = 1;        // Enable Timer2

 //####################################################################################################################################################################

//fill audio buffer with silence on initialization
for (count1 = 0; count1 <= 8000; count1++) {
    audio_sample[count1] = 0;
}

    delay_ms(1);
    count1 = 0;
    EnableInterrupts();       // Enable all interrupts

   while (1) {
   //do nothing
  }

  }