 // Code VGC GPAD 16K - COMPATIBLE AVEC VGC CONNECT | https://www.thingiverse.com/Gaming_Hobby/designs
 // Bibliothèque requise | https://github.com/MHeironimus/ArduinoJoystickLibrary
 // Site web Team VGC | https://sites.google.com/view/team-vgc/

#include <Joystick.h>


const uint8_t PIN_X       = A2;
const uint8_t PIN_Y       = A3;


const uint8_t NUM_BUTTONS = 16;
const uint8_t BUTTON_PINS[NUM_BUTTONS] = {
  1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 14, 15, 18, 19
};

const uint8_t CALIB_SAMPLES      = 50;
const uint8_t DEADZONE_PERCENT   = 10;     // 10 % de zone morte
const float   ZONE_SHRINK_FACTOR = 0.25f;  // 25 % de la course physique

int16_t centerX, centerY;
int16_t deadzoneRaw;

Joystick_ Joystick(
  JOYSTICK_DEFAULT_REPORT_ID,
  JOYSTICK_TYPE_JOYSTICK,
  NUM_BUTTONS, 0,      // nombre de boutons, hatswitch
  true, true,          // axes X et Y
  false, false, false, false,
  false, false, false,    // Z, Rx, Ry, Rz
  false, false             // brake, steering
);

void setup() {
  // Initialise tous les boutons en pull-up interne
  for (uint8_t i = 0; i < NUM_BUTTONS; i++) {
    pinMode(BUTTON_PINS[i], INPUT_PULLUP);
  }

  // false = pas d’envoi auto à chaque modification
  Joystick.begin(false);

  // --- Calibration du centre ---
  long sumX = 0, sumY = 0;
  for (uint8_t i = 0; i < CALIB_SAMPLES; i++) {
    sumX += analogRead(PIN_X);
    sumY += analogRead(PIN_Y);
    delay(5);
  }
  centerX = sumX / CALIB_SAMPLES;
  centerY = sumY / CALIB_SAMPLES;

  deadzoneRaw = (DEADZONE_PERCENT * 1023) / 100 / 2;
}

void loop() {
  // --- Lecture du joystick ---

  // 1) Lecture et recentrage
  int rawX = analogRead(PIN_X) - centerX;
  int rawY = analogRead(PIN_Y) - centerY;

  // 2) Dead-zone
  if (abs(rawX) <= deadzoneRaw) rawX = 0;
  if (abs(rawY) <= deadzoneRaw) rawY = 0;

  // 3) Limites physiques
  int16_t limitX = max(centerX, 1023 - centerX);
  int16_t limitY = max(centerY, 1023 - centerY);

  // 4) Réduction de la zone utile
  float modLimitX = limitX * ZONE_SHRINK_FACTOR;
  float modLimitY = limitY * ZONE_SHRINK_FACTOR;

  // 5) Clamp
  rawX = constrain(rawX, -modLimitX, modLimitX);
  rawY = constrain(rawY, -modLimitY, modLimitY);

  // 6) Conversion en 0…1023
  int16_t x = map(rawX, -modLimitX, modLimitX, 1023, 0);   // axe X inversé
  int16_t y = map(rawY, -modLimitY, modLimitY, 1023, 0);   // axe Y inversé (Haut/Bas)

  Joystick.setXAxis(x);
  Joystick.setYAxis(y);

  // --- Lecture des boutons ---
  for (uint8_t i = 0; i < NUM_BUTTONS; i++) {
    // LOW quand appuyé grâce au pull-up interne
    bool pressed = (digitalRead(BUTTON_PINS[i]) == LOW);
    Joystick.setButton(i, pressed);
  }

  // Envoi du rapport HID
  Joystick.sendState();
  delay(10);
}
