// Thrustmaster Cougar TQS USB Project

#include "Joystick.h"
#include <Wire.h>
#include <Adafruit_ADS1X15.h>
#include <EEPROM.h>

// Create Joystick
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 
  JOYSTICK_TYPE_JOYSTICK, 12, 0,
  true, true, false, true, true, false,
  false, true, false, false, false);

// Set to true to test "Auto Send" mode or false to test "Manual Send" mode.
Adafruit_ADS1115 ads1115;  /* Use this for the 16-bit version */

struct strCalibrationData {
  // 각종 축 MIN 값
  unsigned int minX;
  unsigned int minY;
  unsigned int minAnt;
  unsigned int minRng;
  unsigned int minThtl;
  
  // 각종 축 MAX 값
  unsigned int maxX;
  unsigned int maxY;
  unsigned int maxAnt;
  unsigned int maxRng;
  unsigned int maxThtl;
  
  // 각종 축 Center 값 (미사용)
  unsigned int centerX;
  unsigned int centerY;
  unsigned int centerAnt;
  unsigned int centerRng;
  unsigned int centerThtl;
};

// analog 측정값
unsigned int xAxis           = 0;    // 미니스틱X축
unsigned int yAxis           = 0;    // 미니스틱Y축
unsigned int antAxis         = 0;    // Ant. Elevation 축
unsigned int rngAxis         = 0;    // Range 축
unsigned int throttleAxis    = 0;    // 스로틀축

// 각종 축 Mapping 값
unsigned int mapXAxis        = 0;
unsigned int mapYAxis        = 0;
unsigned int mapAntAxis      = 0;
unsigned int mapRngAxis      = 0;
unsigned int mapThrottleAxis = 0;

// 아두이노 ADC 핀번호
int xPin            = A3;
int yPin            = 10;
int antPin          = A1;
int rngPin          = A0;
int throttlePin     = A2;

// 아두이노 버튼 핀번호
int  btnX1          = 4;
int  btnX2          = 5;
int  btnX3          = 6;
int  btnX4          = 7;

// 아두이노 Pulldown 출력 핀번호
int btnY1           = 8;
int btnY2           = 9;
int btnY3           = 14;

// 필터용 변수
float EMA_ax         = 0.6;
int   EMA_sx         = 0;

float EMA_ay         = 0.6;
int   EMA_sy         = 0;

float EMA_aAnt       = 0.6;
int   EMA_sAnt       = 0;

float EMA_aRng       = 0.6;
int   EMA_sRng       = 0;

float EMA_at         = 0.6;
int   EMA_st         = 0;

// 버튼 현재 값
int currButtonStateX[10] = {0,0,0,0,0,0,0,0,0,0};

// EEPROM 번지수
int addr            = 0;

// 시간측정용
unsigned long currentTime = 0;
boolean  isPressed        = false;
boolean  isSetupEnded     = false;
boolean  Startup          = true;
  
strCalibrationData caliData = {
  // 각종 축 MIN 값
  //142, 131, 0, 0, 137, 696, 664, 749, 749, 681, 0, 0, 0, 0, 0
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

 
void setup() {
  Joystick.begin();

  if (!ads1115.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }

  // Set Range Values
  Joystick.setXAxisRange(0, 32767);
  Joystick.setYAxisRange(0, 32767);
  Joystick.setRxAxisRange(0, 32767);
  Joystick.setRyAxisRange(0, 32767);
  Joystick.setThrottleRange(0, 32767);

  //ads1115.setGain(GAIN_TWOTHIRDS);
  ads1115.setGain(GAIN_ONE);
  ads1115.setDataRate(RATE_ADS1115_860SPS); // 860 samples per second

  EMA_sx    = analogRead(xPin);
  EMA_sy    = analogRead(yPin);
  EMA_sAnt  = analogRead(antPin);
  EMA_sRng  = analogRead(rngPin);
  EMA_st    = analogRead(throttlePin);

  // Initialize Button Pins
  pinMode(btnX1, INPUT);
  pinMode(btnX2, INPUT);
  pinMode(btnX3, INPUT);
  pinMode(btnX4, INPUT);
  pinMode(btnY1, OUTPUT);
  pinMode(btnY2, OUTPUT);
  pinMode(btnY3, OUTPUT);

  Serial.begin(9600);

  EEPROM.get(0, caliData);

  Serial.print(caliData.minX);
  Serial.print(" : ");
  Serial.print(caliData.centerX);
  Serial.print(" : ");
  Serial.print(caliData.maxX);
  Serial.print(" / ");
  Serial.print(caliData.minY);
  Serial.print(" : ");
  Serial.print(caliData.centerY);
  Serial.print(" : ");
  Serial.print(caliData.maxY);
  Serial.print(" / ");
  Serial.print(caliData.minAnt);
  Serial.print(" : ");
  Serial.print(caliData.maxAnt);
  Serial.print(" / ");
  Serial.print(caliData.minRng);
  Serial.print(" : ");
  Serial.print(caliData.maxRng);
  Serial.print(" / ");
  Serial.print(caliData.minThtl);
  Serial.print(" : ");
  Serial.print(caliData.maxThtl);
  Serial.println(" / ");
}

void loop() {

  // Analog축 처리
  analogAxisProcess();

  // 버튼 처리
  buttonMatrixProcess();

  // T6, T3 버튼 5초 입력시 캘리브레이션 시작
  if (currButtonStateX[8] == 0 && currButtonStateX[1] == 0)
  {
    if (isPressed == false)
    {
      isPressed = true;
      currentTime = millis();

      Serial.println(currentTime);
    }

    if (millis() - currentTime > 5000)
    {
      if (isSetupEnded == false)
      {
        Serial.println("SETUP");
        Calibration();
      }
    }
  }
  else if (currButtonStateX[8] == 0 && currButtonStateX[0] == 0)
  {
    if (isPressed == false)
    {
      isPressed = true;
      currentTime = millis();

      Serial.println(currentTime);
    }

    if (millis() - currentTime > 5000)
    {
      if (isSetupEnded == false)
      {
        Serial.println("RESET");
        Reset();
      }
    }
  }
  else
  {
    isPressed    = false;
    isSetupEnded = false;
    currentTime = millis();
  }

  //delay(100);
}

void Calibration()
{
  delay(100);
  Serial.println("--- START SAVE Cougar TQS Calibration DATA ---");

  // Serial.println(EEPROM.length());
  addr = 0;

  Serial.print(caliData.minX);
  Serial.print(" : ");
  Serial.print(caliData.maxX);
  Serial.print(" / ");
  Serial.print(caliData.minY);
  Serial.print(" : ");
  Serial.print(caliData.maxY);
  Serial.print(" / ");
  Serial.print(caliData.minAnt);
  Serial.print(" : ");
  Serial.print(caliData.maxAnt);
  Serial.print(" / ");
  Serial.print(caliData.minRng);
  Serial.print(" : ");
  Serial.print(caliData.maxRng);
  Serial.print(" / ");
  Serial.print(caliData.minThtl);
  Serial.print(" : ");
  Serial.print(caliData.maxThtl);
  Serial.println(" / ");

  EEPROM.put(addr, caliData);
  
//  EEPROM.write( 0, (byte) minX>>8);
//  EEPROM.write( 1, (byte) minX);
//  EEPROM.write( 2, (byte) maxX>>8);
//  EEPROM.write( 3, (byte) maxX);
//  EEPROM.write( 4, (byte) minY>>8);
//  EEPROM.write( 5, (byte) minY);
//  EEPROM.write( 6, (byte) maxY>>8);
//  EEPROM.write( 7, (byte) maxY);
//  EEPROM.write( 8, (byte) minAnt>>8);
//  EEPROM.write( 9, (byte) minAnt);
//  EEPROM.write(10, (byte) maxAnt>>8);
//  EEPROM.write(11, (byte) maxAnt);
//  EEPROM.write(12, (byte) minRng>>8);
//  EEPROM.write(13, (byte) minRng);
//  EEPROM.write(14, (byte) maxRng>>8);
//  EEPROM.write(15, (byte) maxRng);
//  EEPROM.write(16, (byte) minThtl>>8);
//  EEPROM.write(17, (byte) minThtl);
//  EEPROM.write(18, (byte) maxThtl>>8);
//  EEPROM.write(19, (byte) maxThtl);

  //while (addr < EEPROM.length())
//  while (addr < 40)
//  {
//    Serial.print(addr);
//    Serial.print("\t");
//    Serial.print(EEPROM.read(addr));
//    Serial.println();
//    addr++;
//  }
  
  isSetupEnded    = true;
  
  Serial.println("--- END SAVE Cougar TQS Calibration DATA ---");
}

void Reset()
{
  delay(100);
  Serial.println("--- START SAVE Cougar TQS Initial DATA ---");

  // Serial.println(EEPROM.length());
  addr = 0;

  caliData.minX    += 4000;
  caliData.maxX    -= 4000;
  caliData.minY    += 4000;
  caliData.maxY    -= 4000;
  caliData.minAnt  += 4000;
  caliData.maxAnt  -= 4000;
  caliData.minRng  += 400;
  caliData.maxRng  -= 400;
  caliData.minThtl += 4000;
  caliData.maxThtl -= 4000;

  Serial.print(caliData.minX);
  Serial.print(" : ");
  Serial.print(caliData.maxX);
  Serial.print(" / ");
  Serial.print(caliData.minY);
  Serial.print(" : ");
  Serial.print(caliData.maxY);
  Serial.print(" / ");
  Serial.print(caliData.minAnt);
  Serial.print(" : ");
  Serial.print(caliData.maxAnt);
  Serial.print(" / ");
  Serial.print(caliData.minRng);
  Serial.print(" : ");
  Serial.print(caliData.maxRng);
  Serial.print(" / ");
  Serial.print(caliData.minThtl);
  Serial.print(" : ");
  Serial.print(caliData.maxThtl);
  Serial.println(" / ");

  EEPROM.put(addr, caliData);
  
//  EEPROM.write( 0, (byte) minX>>8);
//  EEPROM.write( 1, (byte) minX);
//  EEPROM.write( 2, (byte) maxX>>8);
//  EEPROM.write( 3, (byte) maxX);
//  EEPROM.write( 4, (byte) minY>>8);
//  EEPROM.write( 5, (byte) minY);
//  EEPROM.write( 6, (byte) maxY>>8);
//  EEPROM.write( 7, (byte) maxY);
//  EEPROM.write( 8, (byte) minAnt>>8);
//  EEPROM.write( 9, (byte) minAnt);
//  EEPROM.write(10, (byte) maxAnt>>8);
//  EEPROM.write(11, (byte) maxAnt);
//  EEPROM.write(12, (byte) minRng>>8);
//  EEPROM.write(13, (byte) minRng);
//  EEPROM.write(14, (byte) maxRng>>8);
//  EEPROM.write(15, (byte) maxRng);
//  EEPROM.write(16, (byte) minThtl>>8);
//  EEPROM.write(17, (byte) minThtl);
//  EEPROM.write(18, (byte) maxThtl>>8);
//  EEPROM.write(19, (byte) maxThtl);

  //while (addr < EEPROM.length())
//  while (addr < 40)
//  {
//    Serial.print(addr);
//    Serial.print("\t");
//    Serial.print(EEPROM.read(addr));
//    Serial.println();
//    addr++;
//  }
  
  isSetupEnded    = true;
  
  Serial.println("--- END SAVE Cougar TQS Initial DATA ---");
}

void analogAxisProcess()
{
  //xAxis           = analogRead(xPin);
  //yAxis           = analogRead(yPin);
  //antAxis         = analogRead(antPin);
  rngAxis         = analogRead(rngPin);
  //throttleAxis    = analogRead(throttlePin);

  // Use ADS1115 
  throttleAxis    = ads1115.readADC_SingleEnded(0);
  xAxis           = ads1115.readADC_SingleEnded(2);
  yAxis           = ads1115.readADC_SingleEnded(1);
  //antAxis         = ads1115.readADC_SingleEnded(3);
  antAxis = twosComplement(ads1115.readADC_SingleEnded(3));
  
//  Serial.print("X:");
//  Serial.print(xAxis);
//  Serial.print("  Y:");
//  Serial.print(yAxis);
//  Serial.print("  ANT:");
//  Serial.print(antAxis);
//  Serial.print("  RNG:");
//  Serial.print(mapRngAxis);
//  Serial.print("  Throttle:");
//  Serial.print(throttleAxis);
//  Serial.println();

  if (caliData.minX    > xAxis)        caliData.minX    = xAxis;        caliData.centerX = caliData.minX + ((caliData.maxX - caliData.minX) / 2);
  if (caliData.minY    > yAxis)        caliData.minY    = yAxis;        caliData.centerY = caliData.minY + ((caliData.maxY - caliData.minY) / 2);
  if (caliData.minAnt  > antAxis)      caliData.minAnt  = antAxis;
  if (caliData.minRng  > rngAxis)      caliData.minRng  = rngAxis;
  if (caliData.minThtl > throttleAxis) caliData.minThtl = throttleAxis;
  
  if (caliData.maxX    < xAxis)        caliData.maxX    = xAxis;
  if (caliData.maxY    < yAxis)        caliData.maxY    = yAxis;
  if (caliData.maxAnt  < antAxis)      caliData.maxAnt  = antAxis;
  if (caliData.maxRng  < rngAxis)      caliData.maxRng  = rngAxis;
  if (caliData.maxThtl < throttleAxis) caliData.maxThtl = throttleAxis;

  EMA_sx   = (EMA_ax   * xAxis)        + ((1 - EMA_ax  ) * EMA_sx  );
  EMA_sy   = (EMA_ay   * yAxis)        + ((1 - EMA_ay  ) * EMA_sy  );
  EMA_sAnt = (EMA_aAnt * antAxis)      + ((1 - EMA_aAnt) * EMA_sAnt);
  EMA_sRng = (EMA_aRng * rngAxis)      + ((1 - EMA_aRng) * EMA_sRng);
  EMA_st   = (EMA_at   * throttleAxis) + ((1 - EMA_at  ) * EMA_st  );
  
  mapXAxis        = map(EMA_sx  , caliData.minX  ,  caliData.maxX  ,    32767, 0);
  mapYAxis        = map(EMA_sy  , caliData.minY  ,  caliData.maxY  ,    32767, 0);
  mapAntAxis      = map(EMA_sAnt, caliData.minAnt,  caliData.maxAnt,    0, 32767);
  mapRngAxis      = map(EMA_sRng, caliData.minRng,  caliData.maxRng,    0, 32767);
  mapThrottleAxis = map(EMA_st  , caliData.minThtl, caliData.maxThtl,   0, 32767);

  Joystick.setXAxis(mapXAxis);
  Joystick.setYAxis(mapYAxis);
  Joystick.setRxAxis(mapAntAxis);
  Joystick.setRyAxis(mapRngAxis);
  Joystick.setThrottle(mapThrottleAxis);

//  Serial.print("X:");
//  Serial.print(mapXAxis);
//  Serial.print("  Y:");
//  Serial.println(yAxis);
//  Serial.print("  ANT:");
//  Serial.print(mapAntAxis);
//  Serial.print("  RNG:");
//  Serial.print(mapRngAxis);
//  Serial.print("  Throttle:");
//  Serial.print(mapThrottleAxis);
//  Serial.print(" ||| ");
//  Serial.print(caliData.minX);
//  Serial.print(" : ");
//  Serial.print(caliData.maxX);
//  Serial.print(" / ");
//  Serial.print(caliData.minY);
//  Serial.print(" : ");
//  Serial.print(caliData.maxY);
//  Serial.print(" / ");
//  Serial.print(caliData.minAnt);
//  Serial.print(" : ");
//  Serial.print(caliData.maxAnt);
//  Serial.print(" / ");
//  Serial.print(caliData.minRng);
//  Serial.print(" : ");
//  Serial.print(caliData.maxRng);
//  Serial.print(" / ");
//  Serial.print(caliData.minThtl);
//  Serial.print(" : ");
//  Serial.print(caliData.maxThtl);
//  Serial.println(" / ");
}

void buttonMatrixProcess()
{
  digitalWrite(btnY1, LOW);
  delay(1);
  currButtonStateX[0] = digitalRead(btnX1);
  currButtonStateX[1] = digitalRead(btnX2);
  currButtonStateX[2] = digitalRead(btnX3);
  currButtonStateX[3] = digitalRead(btnX4);
  digitalWrite(btnY1, HIGH);

  digitalWrite(btnY2, LOW);
  delay(1);
  currButtonStateX[4] = digitalRead(btnX1);
  currButtonStateX[5] = digitalRead(btnX2);
  currButtonStateX[6] = digitalRead(btnX3);
  currButtonStateX[7] = digitalRead(btnX4);
  digitalWrite(btnY2, HIGH);

  digitalWrite(btnY3, LOW);
  delay(1);
  currButtonStateX[8] = digitalRead(btnX1);
  currButtonStateX[9] = digitalRead(btnX2);
  digitalWrite(btnY3, HIGH);

  // T1 CURSOR ENABLE
  if (currButtonStateX[9] == 0)
  {
    Joystick.setButton(0, true);
  }
  else
  {
    Joystick.setButton(0, false);
  }
  
  // T2 UP VHF
  if (currButtonStateX[1] == 0)
  {
    Joystick.setButton(1, true);
  }
  else
  {
    Joystick.setButton(1, false);
  }

  // T3 DOWN UHF
  if (currButtonStateX[0] == 0)
  {
    Joystick.setButton(2, true);
  }
  else
  {
    Joystick.setButton(2, false);
  }

  // T4 RIGHT IFF OUT
  if (currButtonStateX[3] == 0)
  {
    Joystick.setButton(3, true);
  }
  else
  {
    Joystick.setButton(3, false);
  }

  // T5 LEFT IFF IN
  if (currButtonStateX[2] == 0)
  {
    Joystick.setButton(4, true);
  }
  else
  {
    Joystick.setButton(4, false);
  }

  // T6 UNCAGE
  if (currButtonStateX[8] == 0)
  {
    Joystick.setButton(5, true);
  }
  else
  {
    Joystick.setButton(5, false);
  }

  // T7 DIGFIGHT OVERRIDE
  if (currButtonStateX[4] == 0)
  {
    Joystick.setButton(6, true);
  }
  else
  {
    Joystick.setButton(6, false);
  }

  // T8 MRM OVERRIDE
  if (currButtonStateX[5] == 0)
  {
    Joystick.setButton(7, true);
  }
  else
  {
    Joystick.setButton(7, false);
  }

  // T9 OPEN AIRBRAKE
  if (currButtonStateX[6] == 0)
  {
    Joystick.setButton(8, true);
  }
  else
  {
    Joystick.setButton(8, false);
  }

  // T10 CLOSE AIRBRAKE
  if (currButtonStateX[7] == 0)
  {
    Joystick.setButton(9, true);
  }
  else
  {
    Joystick.setButton(9, false);
  }

  // T11 NAV MODE
  if ((currButtonStateX[4] == 1) && (currButtonStateX[5] == 1))
  {
    Joystick.setButton(10, true);
  }
  else
  {
    Joystick.setButton(10, false);
  }

  // T12 MID AIRBRAKE
  if ((currButtonStateX[6] == 1) && (currButtonStateX[7] == 1))
  {
    Joystick.setButton(11, true);
  }
  else
  {
    Joystick.setButton(11, false);
  }

//  Serial.print("BTN : ");
//  Serial.print(currButtonStateX[0]);
//  Serial.print(currButtonStateX[1]);
//  Serial.print(currButtonStateX[2]);
//  Serial.print(currButtonStateX[3]);
//  Serial.print(currButtonStateX[4]);
//  Serial.print(currButtonStateX[5]);
//  Serial.print(currButtonStateX[6]);
//  Serial.print(currButtonStateX[7]);
//  Serial.print(currButtonStateX[8]);
//  Serial.print(currButtonStateX[9]);
//  Serial.println(" ");
}

unsigned int twosComplement(unsigned int value)
{
  if (value >= 0x8000){
    //Serial.println("OVER");

    value = 0;
  }
  return value;
}
Posted by 파파울프™
,