#include <Servo.h>

// i made this program by reading forums online + referring to the example programs provided in arduino IDE
// (specifically blinkwithoutdelay)

int buzzer_pin = D2;
int servo_pin = D3;

Servo servo_motor;

int tempo = 100;
bool signal = false;
int servo_pos = 0;
bool servo_increasing = true;

unsigned long previous_hand = 0;
unsigned long previous_flip = 0;
unsigned long previous_note = 0;

const int hand_interval = 5;
unsigned int curr_note = 0;
bool playing = false;

char sheet_music[37] = {'D','D','B','B','G','G','N','G','D','D','D','A','A','F','F','N','F','D','D','D','A','A','F','F','N','F','C','C','N','C','C','E','E','N','E','F','F'};

void setup() {
  servo_motor.attach(servo_pin);
  pinMode(buzzer_pin, OUTPUT);
  servo_motor.write(0);
}

void loop() {
  unsigned long current_millis = millis();
  wave_hand(current_millis);
  crab_rave(current_millis);
}

void wave_hand(unsigned long current_time) {
  if (previous_hand <= current_time - hand_interval) {
    if (servo_increasing){
      servo_pos += 1;
    }
    else {
      servo_pos -= 1;
    }
    servo_motor.write(servo_pos);
    if (servo_pos == 180 || servo_pos == 0) {
      servo_increasing = !servo_increasing;
    }
    previous_hand = current_time;
  }
}

// tuned all of the keys by looking up the frequencies of the notes in the middle octave.
// then tuned by ear using youtube 'tuning note' vids
void play_A() {
  play_note(568);
}
void play_B() {
  play_note(536);
}
void play_C() {
  play_note(956);
}
void play_D() {
  play_note(852);
}
void play_E() {
  play_note(758);
}
void play_F() {
  play_note(716);
}
void play_G() {
  play_note(638);
}

void play_note(int half_freq) {
  unsigned long current_micros = micros();
  if (previous_flip <= current_micros - half_freq) {
    digitalWrite(buzzer_pin, signal);
    signal = !signal;
    previous_flip = current_micros;
  }
}

void crab_rave(unsigned long current_time) {
  if (!playing) {
    playing = true;
    curr_note = 0;
  }
  else {
    note_map(sheet_music[curr_note]);
    if (sheet_music[curr_note] == 'N') {
      if (previous_note <= current_time - (tempo / 4)) {
        curr_note += 1;
        previous_note = current_time;
      }
    }
    else {
      if (previous_note <= current_time - tempo) {
        curr_note += 1;
        previous_note = current_time;
      }
    }
    if (curr_note >= sizeof(sheet_music)) {
      curr_note = 0;
    }
  }
}

void note_map(char note) {
  switch (note) {
    case 'A':
      play_A();
      break;
    case 'B':
      play_B();
      break;
    case 'C':
      play_C();
      break;
    case 'D':
      play_D();
      break;
    case 'E':
      play_E();
      break;
    case 'F':
      play_F();
      break;
    case 'G':
      play_G();
      break;
    case 'N':
      break;
  }
}