#define PIN_TRIGGER 13 // IR LED
#define PIN_SENSOR A0 // Distance sensor (GP2D12)
#define PIN_POT A1 // Parameter potentiometer
#define PIN_SWITCH 8 // Mode switch

#define INTERVAL 1000
#define N_MEASURE 4
#define PREVENT_SLEEP_INTERVAL 270000

char count;
unsigned long prevent_sleep = 0;
unsigned long last_shot = 0;

void trigger() {
  // Nikon Remote Emulator by Gough Lui
  // https://goughlui.com/2013/12/06/teardown-and-project-clone-nikon-ml-l3-ir-remote-and-emulation/
  count = 0;
  while(count < 3) {
    tone(PIN_TRIGGER, 38000);
    delay(2);
    noTone(PIN_TRIGGER);
    delay(28);
    tone(PIN_TRIGGER, 38000);
    delayMicroseconds(200);
    noTone(PIN_TRIGGER);
    delayMicroseconds(1500);
    tone(PIN_TRIGGER, 38000);
    delayMicroseconds(200);
    noTone(PIN_TRIGGER);
    delayMicroseconds(3300);
    tone(PIN_TRIGGER, 38000);
    delayMicroseconds(200);
    noTone(PIN_TRIGGER);
    delayMicroseconds(100);
    delay(63);
    
    count ++;
  }
  prevent_sleep = millis() + PREVENT_SLEEP_INTERVAL;
  delay(INTERVAL);
}

int measure() {
  int result = 0;
  for(char i=0; i<N_MEASURE; i++) {
    result += analogRead(PIN_SENSOR);
  }
  return result / N_MEASURE;
}

void setup() {
  pinMode(PIN_SWITCH, INPUT_PULLUP);
  pinMode(PIN_TRIGGER, OUTPUT);
  digitalWrite(PIN_TRIGGER, LOW);
}

void loop() {
  if(digitalRead(PIN_SWITCH)) { // Sensor mode
    unsigned int threshold = map(analogRead(PIN_POT), 0, 1023, 81, 532);
    if(measure() > threshold) {
      trigger();
    }
    else if(millis() > prevent_sleep) {
      trigger();
    }
  } else { // Interval mode
    unsigned long interval = map(analogRead(PIN_POT), 0, 1023, 2000, 300000);
    if(millis() > last_shot + interval) {
      last_shot = millis();
      trigger();
    }
  }
}
