#include <Wire.h>                 // Standard I2C library for ESP32
#include <LiquidCrystal_I2C.h>     // LCD I2C library

// Pin Definitions
const int potPin = 34;      // Slide Potentiometer connected to GPIO34 (Analog Input)
const int encCLK = 25;      // Rotary Encoder CLK connected to GPIO25
const int encDT = 26;       // Rotary Encoder DT connected to GPIO26
const int encSW = 33;       // Rotary Encoder Switch connected to GPIO33
const int buttonPin = 32;   // Pushbutton connected to GPIO32

// LCD Settings
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD I2C address, 16 chars, 2 rows

// Global Variables
int volume = 0;
int songPosition = 0;         // This will hold the position value, starting at 0
String direction = "CW";      // Holds direction of rotation ("CW" for clockwise, "CCW" for counterclockwise)
bool songPlaying = false;     // For tracking play/stop status
int lastCLKState = LOW;       // Previous state of the CLK pin
int lastButtonState = HIGH;   // Previous state of the button pin

void setup() {
  // Initialize Serial Monitor for debugging
  Serial.begin(9600);

  // Initialize pins
  pinMode(potPin, INPUT);
  pinMode(encCLK, INPUT);
  pinMode(encDT, INPUT);
  pinMode(encSW, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);
  
  // Initialize I2C for the LCD
  Wire.begin();        // Default I2C pins: SDA on GPIO21 and SCL on GPIO22

  // Initialize LCD
  lcd.begin(16, 2);    // 16 columns and 2 rows
  lcd.backlight();     // Turn on the LCD backlight

  // Display initial values on the LCD
  lcd.setCursor(0, 0);
  lcd.print("Vol: 0 Stop");  // Initial volume and play/stop state
  lcd.setCursor(0, 1);
  lcd.print("Pos: 0 CW");    // Initial position and direction

  lastCLKState = digitalRead(encCLK);  // Set initial state
}

void loop() {
  // Handle Slide Potentiometer (Volume Control)
  int potValue = analogRead(potPin);
  volume = map(potValue, 0, 4095, 0, 127);  // Map potentiometer value (0-4095) to range (0-127)

  // Update Volume and Play/Stop status on LCD
  lcd.setCursor(5, 0);
  lcd.print(volume);
  lcd.print(" ");  // Pad with space to clear any leftover digits
  lcd.print(songPlaying ? "Play " : "Stop");

  // Handle Rotary Encoder (Song Position Control)
  int currentCLKState = digitalRead(encCLK);
  int currentDTState = digitalRead(encDT);

  if (currentCLKState != lastCLKState) {  // Detect CLK state change (rising or falling edge)
    if (currentCLKState == HIGH && currentDTState == LOW) {
      // Clockwise rotation
      direction = "CW";
      songPosition++;  // Increment the song position
    } 
    else if (currentCLKState == HIGH && currentDTState == HIGH) {
      // Counterclockwise rotation
      direction = "CCW";
      songPosition--;  // Decrement the song position
    }

    // Constrain song position to stay within -10 to 10
    songPosition = constrain(songPosition, -10, 10);

    // Update the LCD Display for position and direction
    lcd.setCursor(0, 1);
    lcd.print("Pos: ");
    lcd.print(songPosition);   // Display the song position
    lcd.print(" ");            // Clear any leftover characters
    lcd.print(direction);      // Display the direction (CW or CCW)
    lcd.print("   ");          // Clear leftover characters
  }

  lastCLKState = currentCLKState;  // Update the last state

  // Handle Pushbutton (Play/Stop Toggle)
  int buttonState = digitalRead(buttonPin);
  if (buttonState == LOW && lastButtonState == HIGH) {
    songPlaying = !songPlaying;  // Toggle play/stop state

    // Update Play/Stop status on LCD immediately next to volume
    lcd.setCursor(5, 0);
    lcd.print(volume);
    lcd.print(" ");
    lcd.print(songPlaying ? "Play " : "Stop ");
  }
  lastButtonState = buttonState;  // Update button state for next loop

  // Small delay to prevent rapid flickering
  delay(50);
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND
pot1:VCC
pot1:SIG
pot1:GND