#include <Arduino.h>
#line 1 "/home/arduino/ArduinoApps/demo_4_hc-sr04-ultrasonic-distance-measurement/sketch/sketch.ino"
/*
 * Experiment 5: HC-SR04 Ultrasonic Distance Measurement + Buzzer Alert
 * Function: Measure distance, buzzer beeps faster when closer
 * Hardware: EP-0257 Shield + HC-SR04 + Buzzer
 */

#define TRIG_PIN 4
#define ECHO_PIN 5
#define BUZZER_PIN 6  // Buzzer pin

#line 11 "/home/arduino/ArduinoApps/demo_4_hc-sr04-ultrasonic-distance-measurement/sketch/sketch.ino"
void setup();
#line 20 "/home/arduino/ArduinoApps/demo_4_hc-sr04-ultrasonic-distance-measurement/sketch/sketch.ino"
void loop();
#line 41 "/home/arduino/ArduinoApps/demo_4_hc-sr04-ultrasonic-distance-measurement/sketch/sketch.ino"
void handleBuzzer(long distance);
#line 80 "/home/arduino/ArduinoApps/demo_4_hc-sr04-ultrasonic-distance-measurement/sketch/sketch.ino"
long measureDistance();
#line 11 "/home/arduino/ArduinoApps/demo_4_hc-sr04-ultrasonic-distance-measurement/sketch/sketch.ino"
void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  
  Serial.begin(115200);
  Serial.println("Experiment 5: Ultrasonic Distance + Buzzer");
}

void loop() {
  long distance = measureDistance();
  
  // Serial output
  Serial.print("Distance: ");
  if (distance >= 0) {
    Serial.print(distance);
    Serial.println(" cm");
  } else if (distance == -1) {
    Serial.println("No signal!");
  } else if (distance == -2) {
    Serial.println("Out of range!");
  }
  
  // Buzzer alert logic
  handleBuzzer(distance);
  
  delay(100);  // Base sampling interval
}

// Buzzer control: shorter interval when closer
void handleBuzzer(long distance) {
  static unsigned long lastBeepTime = 0;
  
  unsigned long currentTime = millis();
  
  // Error state: warning beep every second
  if (distance < 0) {
    if (currentTime - lastBeepTime >= 1000) {
      tone(BUZZER_PIN, 1000, 200);
      lastBeepTime = currentTime;
    }
    return;
  }
  
  // Safe distance: silent (> 200cm)
  if (distance > 200) {
    noTone(BUZZER_PIN);
    return;
  }
  
  // Calculate beep interval: closer = shorter interval
  // 200cm -> 2000ms, 10cm -> 100ms
  unsigned long beepInterval = map(distance, 10, 200, 100, 2000);
  beepInterval = constrain(beepInterval, 100, 2000);
  
  // Closer = higher pitch and longer beep
  int frequency = map(distance, 10, 200, 2000, 500);
  int duration = map(distance, 10, 200, 300, 100);
  
  frequency = constrain(frequency, 500, 2000);
  duration = constrain(duration, 100, 300);
  
  // Execute beep
  if (currentTime - lastBeepTime >= beepInterval) {
    tone(BUZZER_PIN, frequency, duration);
    lastBeepTime = currentTime;
  }
}

long measureDistance() {
  // Send trigger pulse
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  // Read echo pulse duration
  long duration = pulseIn(ECHO_PIN, HIGH, 30000);
  
  // Calculate distance (cm)
  long distance = duration * 0.01715;
  
  if (duration == 0) return -1;
  if (distance > 400 || distance < 2) return -2;
  
  return distance;
}
