#include <WebServer.h>
#include <DNSServer.h>
#include <ESP32Servo.h>
// --- PIN MAPPING (DevKit V1) ---
#define IN1 14
#define IN2 27
#define ENA 33
#define IN3 26
#define IN4 25
#define ENB 32
#define TRIG 5
#define ECHO 18
#define SERVO_PIN 12
WebServer server(80);
DNSServer dnsServer;
Servo radarServo;
// --- GLOBAL VARIABLES ---
int mode = 0; // 0: Manual, 1: Auto, 2: Radar
bool lastSelect = false;
float smoothDist = 100.0;
float currentSpeed = 0;
int servoPos = 90;
int servoStep = 2;
unsigned long prevMs = 0;
// High-Tech Radar GUI HTML
const char* RADAR_GUI = R"rawliteral(
<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width,initial-scale=1'>
<style>body{background:#000;color:#0f0;text-align:center;font-family:monospace;margin:0;overflow:hidden;}
canvas{width:98vw;max-width:500px;margin-top:5vh;filter:drop-shadow(0 0 15px #0f0);}</style></head>
<body><h2>PRO RADAR SYSTEM</h2><canvas id='rd'></canvas><h3 id='tx'>SCANNING...</h3>
<script>
const cv=document.getElementById('rd'),ctx=cv.getContext('2d');cv.width=500;cv.height=500;
let d=100,a=90,la=90;
function draw(){
ctx.fillStyle='rgba(0,10,0,0.1)';ctx.fillRect(0,0,500,500);const cx=250,cy=250,r=230;
la+=(a-la)*0.12;ctx.strokeStyle='#030';ctx.lineWidth=1;
for(let i=1;i<=4;i++){ctx.beginPath();ctx.arc(cx,cy,r*(i/4),0,Math.PI*2);ctx.stroke();}
let rad=(la-90)*Math.PI/180;ctx.strokeStyle='#0f0';ctx.lineWidth=4;ctx.beginPath();
ctx.moveTo(cx,cy);ctx.lineTo(cx+r*Math.cos(rad),cy+r*Math.sin(rad));ctx.stroke();
if(d<100){let tr=d*(r/100);ctx.fillStyle='red';ctx.beginPath();ctx.arc(cx+tr*Math.cos(rad),cy+tr*Math.sin(rad),10,0,6.28);ctx.fill();}
requestAnimationFrame(draw);}
setInterval(()=>{fetch('/data').then(res=>res.json()).then(j=>{d=j.d;a=j.a;document.getElementById('tx').innerText=d+'cm | '+a+'deg';});},50);
draw();</script></body></html>)rawliteral";
// --- MOTOR CONTROL ---
void applyMotors(int s1, int s2, int s3, int s4, int target) {
  float ramp = 7.0; 
  if (currentSpeed < target) currentSpeed += ramp;
  else if (currentSpeed > target) currentSpeed -= ramp;
  digitalWrite(IN1, s1); digitalWrite(IN2, s2);
  digitalWrite(IN3, s3); digitalWrite(IN4, s4);
  ledcWrite(ENA, (int)currentSpeed); 
  ledcWrite(ENB, (int)currentSpeed);
}
// --- ULTRASONIC SENSOR ---
float getDist() {
  digitalWrite(TRIG, LOW); delayMicroseconds(2);
  digitalWrite(TRIG, HIGH); delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  long dur = pulseIn(ECHO, HIGH, 25000);
  float d = (dur == 0) ? 100 : dur * 0.034 / 2;
  smoothDist = (smoothDist  0.75) + (d  0.25); // Butter smooth filtering
  return smoothDist;
}
void setup() {
  pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT);
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
  
  radarServo.attach(SERVO_PIN);
  ledcAttach(ENA, 1000, 8); 
  ledcAttach(ENB, 1000, 8);
  
  Dabble.begin("Swornim_AWD");
  
  server.on("/", [](){ server.send(200, "text/html", RADAR_GUI); });
  server.on("/data", [](){
    server.send(200, "application/json", "{\"d\":"+String((int)smoothDist)+",\"a\":"+String(servoPos)+"}");
  });
}
void loop() {
  Dabble.processInput();
  unsigned long now = millis();
  
  // MODE TOGGLE (SELECT BUTTON)
  if (GamePad.isSelectPressed() && !lastSelect) {
    mode = (mode + 1) % 3;
    currentSpeed = 0;
    if (mode == 2) {
      WiFi.softAP("Swornim_Radar", "12345678");
      dnsServer.start(53, "*", WiFi.softAPIP()); server.begin();
    } else {
      dnsServer.stop(); WiFi.softAPdisconnect(true);
    }
    delay(400);
  }
  lastSelect = GamePad.isSelectPressed();
  if (mode == 0) { // MANUAL MODE
    if (GamePad.isUpPressed()) applyMotors(1,0,1,0,255);
    else if (GamePad.isDownPressed()) applyMotors(0,1,0,1,255);
    else if (GamePad.isLeftPressed()) applyMotors(0,1,1,0,220);
    else if (GamePad.isRightPressed()) applyMotors(1,0,0,1,220);
    else applyMotors(0,0,0,0,0);
    getDist();
  } 
  else if (mode == 1) { // AUTO MODE (OBSTACLE AVOIDANCE)
    if (getDist() > 35) applyMotors(1,0,1,0,180);
    else { applyMotors(0,1,1,0,230); delay(650); }
  } 
  else if (mode == 2) { // RADAR MODE
    applyMotors(0,0,0,0,0);
    dnsServer.processNextRequest(); server.handleClient();
    if (now - prevMs > 40) {
      servoPos += (servoStep * 2);
      if (servoPos >= 165 || servoPos <= 15) servoStep *= -1;
      radarServo.write(servoPos);
      getDist();
      prevMs = now;
    }
  }
}
readers loved this