
/*
  EasyJoystick - Arduino library for analog joystick modules

  Provides simple directional input (up, down, left, right, center)
  from 2-axis analog joysticks such as the KY-023.

  Author: Seth Kinzel
  License: MIT
  Repository: https://github.com/SethKinzel/EasyJoystick
*/


#include <Arduino.h>
#include "EasyJoystick.h"

void EasyJoystick::begin(int8_t newXPin, int8_t newYPin, bool newFlipX, bool newFlipY) {
  xPin = newXPin;
  yPin = newYPin;
  flipX = newFlipX;
  flipY = newFlipY;
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
}

void EasyJoystick::loop() {
  previousState = currentState;
  
  // read the joystick
  int16_t x = analogRead(xPin);
  if (flipX) x = map(x, 0, 1023, 1023, 0);
  x = x - 512;
  int16_t y = analogRead(yPin);
  if (flipY) y = map(y, 0, 1023, 1023, 0);
  y = y - 512;

  // check to see if it's still in the "big zone"
  bool inBigZone;
  if (currentState == MIDDLE) {
    inBigZone = (abs(x) < centerThreshold + debounceMiddle && abs(y) < centerThreshold + debounceMiddle);
  } else if (currentState == UP) {
    inBigZone = (abs(y) > centerThreshold - debounceMiddle && abs(y) + debounceEdge > abs(x) && y > 0);
  } else if (currentState == DOWN) {
    inBigZone = (abs(y) > centerThreshold - debounceMiddle && abs(y) + debounceEdge > abs(x) && y < 0);
  } else if (currentState == LEFT) {
    inBigZone = (abs(x) > centerThreshold - debounceMiddle && abs(x) + debounceEdge > abs(y) && x < 0);
  } else if (currentState == RIGHT) {
    inBigZone = (abs(x) > centerThreshold - debounceMiddle && abs(x) + debounceEdge > abs(y) && x > 0);
  } else {
    inBigZone = false;
  }

  // if it's not in the "big zone", find out where it is
  if (!inBigZone) {
    // find the "normal zone"
    // it will always be in exactally one "normal zone"
    if (abs(x) < centerThreshold && abs(y) < centerThreshold) {
      currentState = MIDDLE;
    }
    else {
      if (abs(x) > abs(y)) {
        currentState = x > 0 ? RIGHT : LEFT; //this is called a ternary operator
      } else {
        currentState = y > 0 ? UP : DOWN;
      }
    }
  }
}

int8_t EasyJoystick::getState() {
  return currentState;
}

bool EasyJoystick::changed() {
  return (currentState != previousState && previousState != NONE && currentState != NONE);
}

bool EasyJoystick::isMiddle() {
  return (currentState == MIDDLE);
}

bool EasyJoystick::isUp() {
  return (currentState == UP);
}

bool EasyJoystick::isDown() {
  return (currentState == DOWN);
}

bool EasyJoystick::isLeft() {
  return (currentState == LEFT);
}

bool EasyJoystick::isRight() {
  return (currentState == RIGHT);
}

bool EasyJoystick::isUDLR() {
  return (currentState == UP || currentState == DOWN || currentState == LEFT || currentState == RIGHT);
}

bool EasyJoystick::newMiddle() {
  return (changed() && currentState == MIDDLE);
}

bool EasyJoystick::newUp() {
  return (changed() && currentState == UP);
}

bool EasyJoystick::newDown() {
  return (changed() && currentState == DOWN);
}

bool EasyJoystick::newLeft() {
  return (changed() && currentState == LEFT);
}

bool EasyJoystick::newRight() {
  return (changed() && currentState == RIGHT);
}

bool EasyJoystick::newUDLR() {
  return (changed() && (currentState == UP || currentState == DOWN || currentState == LEFT || currentState == RIGHT));
}
