#include <hardware/pwm.h>
#define MODESWITCH_PIN_A 0
#define MODESWITCH_PIN_B 1
#define PUSHBUTTON_PIN 6
#define VOCT_PIN 26
#define FREQ_POT_PIN 27
#define INV_POT_PIN 28
#define CHORD_POT_PIN 29
#define DEBUG_MODE false
#define SAMPLES 512

int wave[SAMPLES];
float volume_envelope = 0.0;
float pitch_envelope = 0.0;


bool push_sw, old_push_sw;//push sw
int freq_pot;
float osc_freq;

int chord_pot;
float volume_decay;

int inv_pot;
float pitch_decay;

float osc_progress = 0;
int slice_num = 0;
int is_on = 0;



void setup() {
  // Mode select switch is a On-Off-On switch with the outer pins connected
  // to the pins 0 and 1. 
  pinMode(MODESWITCH_PIN_A, INPUT_PULLUP);
  pinMode(MODESWITCH_PIN_B, INPUT_PULLUP);

  // Push Button
  pinMode(PUSHBUTTON_PIN, INPUT_PULLUP);//push sw

  for (int i = 0; i < SAMPLES; i++) {
    wave[i] = (sin(2 * M_PI * i  / 512)) * 511;
  }

  //-------------------PWM setting-------------------------------
  gpio_set_function(2, GPIO_FUNC_PWM);// set GP2 function PWM
  slice_num = pwm_gpio_to_slice_num(2);// GP2 PWM slice

  pwm_clear_irq(slice_num);
  pwm_set_irq_enabled(slice_num, true);
  irq_set_exclusive_handler(PWM_IRQ_WRAP, on_pwm_wrap);
  irq_set_enabled(PWM_IRQ_WRAP, true);

  // Set PWM frequency
  pwm_set_clkdiv(slice_num, 4);
  pwm_set_wrap(slice_num, 1023); // Resolution
  pwm_set_enabled(slice_num, true); // PWM output enable
  
}

void loop() {
  // put your main code here, to run repeatedly:
  old_push_sw = push_sw;
  freq_pot = analogRead(FREQ_POT_PIN);
  chord_pot = map(analogRead(CHORD_POT_PIN), 0, 1023, 1023, 0);
  inv_pot = map(analogRead(INV_POT_PIN), 0, 1023, 1023, 0);

  osc_freq = 0.15 + freq_pot/1023.0;
  volume_decay = 0.00002 + (float)chord_pot/1023.0/1000.0;
  float _pitch_decay = (inv_pot/1023.0);
  pitch_decay = 0.00001 + (float)inv_pot/1023.0/500.0;

  //  -------------------push sw , play wave-------------------------------
  push_sw = digitalRead(PUSHBUTTON_PIN);
  // TODO: Add propper debouncing for the button here
  if (push_sw == 0 && old_push_sw == 1) {//when push sw ON
    // Change the selected waveform and ensure the selection is within bounds+1
    //
  }
  if (push_sw == 0) {
    is_on = 1;
    if (old_push_sw == 1) {
      osc_progress = 0;
      volume_envelope = 1.0;
      pitch_envelope = 2.0;
    }
  }else {
    is_on = 0;
  }
}


// Timer that pushes out the actual audio. 
void on_pwm_wrap() {
  pwm_clear_irq(slice_num);

  pitch_envelope -= pitch_decay;
  if (pitch_envelope < 0.0001) {
    pitch_envelope = 0.0;
  }

  osc_progress += osc_freq + pitch_envelope;

  if (osc_progress > SAMPLES) {
    osc_progress = 0;
  }

  volume_envelope -= volume_decay;
  if (volume_envelope < 0.0001) {
    volume_envelope = 0.0;
  }

  pwm_set_chan_level(slice_num, PWM_CHAN_A, volume_envelope*wave[(int)osc_progress]/2+511);
}