/*
		World's smallest remote control joystick
		Receiver: ESP8266/ESP32 + ESP-NOW
		Markus Opitz 2026
		instructables.com
*/

#include <espnow.h>

#if defined (ARDUINO_ARCH_ESP8266)
	#include <ESP8266WiFi.h>
	#include <Servo.h>
#elif defined(ESP32)
	#include <WiFi.h>
	#include <ESP32Servo.h>
#else
#error Architecture unrecognized by this code.
#endif



// data structure (MUST be identical!)
enum Direction {
  DIR_NONE = 0,
  DIR_UP,
  DIR_DOWN,
  DIR_LEFT,
  DIR_RIGHT,
  DIR_CENTER
};

// ===== data struct from ESP-NOW =====
typedef struct {
  uint8_t direction;
} ControlData;

ControlData data;

Servo RL; Servo UD;
const int servoPinRL = D4;
const int servoPinUD = D8;

int currentUD = 90;
int currentRL = 90;
const int LEDpin = D7;
int center = 90;
int step = 20;
bool lastButtonState = false;


// for ESP8266 as receiver uncomment this:
void onReceive(uint8_t *mac, uint8_t *incomingData, uint8_t len) {

// for ESP32 as receiver uncomment this:
//void onReceive(const esp_now_recv_info *info, const uint8_t *incomingData, int len) {


  memcpy(&data, incomingData, sizeof(data));

  switch(data.direction) {

    case DIR_UP:
      Serial.println("^");
      currentUD = currentUD + step;
      if (currentUD >= 180) currentUD =180;
      UD.write(currentUD);
      break;

    case DIR_DOWN:
      Serial.println("v");
      currentUD = currentUD - step;
      if (currentUD <=0) currentUD =0;
      UD.write(currentUD);
      break;

    case DIR_LEFT:
      Serial.println("<--");
      currentRL = currentRL + step;
      if (currentRL >= 180) currentRL =180;
      RL.write(currentRL);
      break;

    case DIR_RIGHT:
      Serial.println("-->");
      currentRL = currentRL - step;
      if (currentRL <= 0) currentRL =0;
      RL.write(currentRL);
      break;

    case DIR_CENTER:
      Serial.println("CENTER");
      currentRL = center; currentUD = center;
      //RL.write(currentRL);UD.write(currentUD);
      digitalWrite(D1, HIGH); delay(1000);
      digitalWrite(D1, LOW);

      break;

    case DIR_NONE:
    default:
      break;
  }
}

void setup() {
  Serial.begin(115200);

  pinMode(D1, OUTPUT);
  digitalWrite(D1, LOW);

  WiFi.mode(WIFI_STA);

  if (esp_now_init() != 0) {
    Serial.println("ESP-NOW init failed");
    return;
  }

  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(onReceive);

  Serial.println("receiver ready");

  //  servo Setup
  RL.attach(servoPinRL); UD.attach(servoPinUD);
  RL.write(90); UD.write(90);delay(10);
  Serial.println("servos ready");

  pinMode(LEDpin, OUTPUT);
  digitalWrite(LEDpin, LOW);
}

void loop() {
  // all happens in callback
}