/*
 *  Erik Hansen
 *  March 5, 2023
 *  Lab 4 Project
 */

// Binary Display Class
class BinaryDisplay {
  // Init values
  int _pin1, _pin2, _pin4, _pin8;

  public:
      //
      void setup(int pin1, int pin2, int pin4, int pin8) {
        pinMode(pin1, OUTPUT);
        pinMode(pin2, OUTPUT);
        pinMode(pin4, OUTPUT);
        pinMode(pin8, OUTPUT);
        _pin1 = pin1;
        _pin2 = pin2;
        _pin4 = pin4;
        _pin8 = pin8;
      }
      //
      void display(int iValue) {
        digitalWrite(_pin1, (iValue & 1) ? HIGH : LOW);
        digitalWrite(_pin2, (iValue & 2) ? HIGH : LOW);
        digitalWrite(_pin4, (iValue & 4) ? HIGH : LOW);
        digitalWrite(_pin8, (iValue & 8) ? HIGH : LOW);
      }
};

// Declarations
BinaryDisplay bd;           // Binary Display
const int potPinPos = A0;   // Potentiometer
const int potPinNeg = A1;   // Potentiometer
#define BUTTON_PIN 9        // Pause button
const int rgbs[] = {6,7,8}; // RGB LED pins

// Values and Variables
int potValuePos = 0;    // Value from positive potentiometer
int potValueNeg = 0;    // Value from negative potentiometer
int outputValuePos = 0; // Value from positive potentiometer
int outputValueNeg = 0; // Value from negative potentiometer
int outputValue = 0;    // Total value from potientiometers
int totalValue = 0;     // Total value (from Counter01 and Counter16)
int Counter01 = 0;      // 1 Value Counter
int Counter16 = 0;      // 16 Value Counter
bool paused = false;    // Button state (pause/unpaused)

void setup() {
  // Initialization of the Serial Connection
  Serial.begin(9600);
  Serial.println("Assignment 4, Counting in Binary (With Poteniometer -8 thru 8) By Erik Hansen");
  Serial.println();
  // Binary Display Setup
  bd.setup(5,4,3,2);                  // Green = 1, Yellow = 2, Blue = 4, Red = 8
  pinMode(rgbs[0], OUTPUT);           // Red value
  pinMode(rgbs[1], OUTPUT);           // Green value
  pinMode(rgbs[2], OUTPUT);           // Blue value
  pinMode(BUTTON_PIN, INPUT_PULLUP);  // Pause button
}

void loop() {
  // Pot
  potValuePos = analogRead(potPinPos);
  outputValuePos = map(potValuePos, 0, 1023, 0, 8);

  potValueNeg = analogRead(potPinNeg);
  outputValueNeg = map(potValueNeg, 0, 1023, 0, -8);

  outputValue = outputValuePos + outputValueNeg;

  // Check pause state
  if (digitalRead(BUTTON_PIN) == LOW) {
    paused = !paused;
    delay(250); // Debounce
  }

  if (!paused) {
    // Increment/Decrease Counter01 each increment
    Counter01 = Counter01 + outputValue;

    // Check if Counter01 value is greater than 16 
    if (Counter01 > 16) {
      // If greater, reset Counter01 (modulo if greater) and increment Counter16
      Counter01 = Counter01 % 16;
      Counter16++;
      // Check if Counter16 is greater than 3
      if (Counter16 > 3) {
        // If greater, reset Counter16
        Counter16 = 0;
      }
    }

    // Check if Counter01 is lesser than 0
    if (Counter01 < 0) {
      // If lesser, set Counter01 to max () and decrease Counter16 
      Counter01 = Counter01 % 16 + 16;
      Counter16--;
      // Check if Counter16 is less than 0
      if (Counter16 < 0) {
        // If lesser, set Counter16 to max (3)
        Counter16 = 3;
      }
    }

    // Run display to display current count in binary
    bd.display(Counter01);

    // Switch case to check the current value of Counter16
    switch (Counter16) {
      case 1: // Value of 16
        analogWrite(rgbs[0], 255);
        analogWrite(rgbs[1], 0);
        analogWrite(rgbs[2], 0);
        break;
      case 2: // Value of 32
        analogWrite(rgbs[0], 0);
        analogWrite(rgbs[1], 255);
        analogWrite(rgbs[2], 0);
        break;
      case 3: // Value of 48
        analogWrite(rgbs[0], 0);
        analogWrite(rgbs[1], 0);
        analogWrite(rgbs[2], 255);
        break;
      default: // Default value (>16 and <64)
        analogWrite(rgbs[0], 0);
        analogWrite(rgbs[1], 0);
        analogWrite(rgbs[2], 0);
    }

    // Find the total value
    totalValue = (Counter16 * 16) + Counter01;

    // Print out values
    Serial.print("Increment: ");
    Serial.print(outputValue);
    Serial.print(", Counter16: ");
    Serial.print(Counter16);
    Serial.print(", Counter01: ");
    Serial.print(Counter01);
    Serial.print(", Total: ");
    Serial.print(totalValue);
    Serial.println();
  }
  delay(750);
}