#include <Wire.h>
#include <Keypad.h>
#include <SD.h>
#include <TMRpcm.h>
#include <SPI.h>

// Define the keys array
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'A','B','C','D'},
  {'E','F','G','H'},
  {'I','J','K','L'},
  {'M','N','O','P'}
};

// Pin Definitions
const int ENCODER_CLK = A6;
const int ENCODER_DT  = A7;
const int ENCODER_SW  = 6;
const int greenPin = 8;
const int bluePin = 7;
const byte rowPins[ROWS] = {5, 4, 3, 2};
const byte colPins[COLS] = {A3, A2, A1, A0};
const int speakerPin = 9;
const int SD_ChipSelectPin = 10;

// Volume Settings
const int lowVolume = 250;
const int highVolume = 350;

// Global Objects
Keypad keypad = Keypad(makeKeymap((char*)keys), rowPins, colPins, ROWS, COLS);
TMRpcm tmrpcm;

// Rotary status
int lastClk = HIGH;

// Function Declarations
void setup();
void loop();
void initialize();
void playSound(char key);
void blinkLED(int pin, int duration, int repeat);

// Setup Function
void setup() {
  Serial.begin(9600); // Initialize serial communication
  initialize();
}

// Loop Function
void loop() {
  char key = keypad.getKey();
  if (key) {
    digitalWrite(bluePin, HIGH);
    playSound(key);
    Serial.println("Button pressed: " + String(key));
  } else {
    return;
  }
}

// Initialization Function
void initialize() {
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);
  pinMode(ENCODER_SW, INPUT_PULLUP);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  digitalWrite(greenPin, LOW);
  digitalWrite(bluePin, LOW);
  
  if (!SD.begin(SD_ChipSelectPin)) {
    Serial.println("SD card initialization failed!");
    blinkLED(bluePin, 250, 4);
    blinkLED(greenPin, 250, 2);
    return;
  }
  
  Serial.println("SD card initialized successfully.");
  blinkLED(greenPin, 300, 3);
}
// Play Sound Function
void playSound(char key) {
  tmrpcm.speakerPin = speakerPin;
  tmrpcm.setVolume(4);
  if (key >= 'A' && key <= 'P') {
    tmrpcm.setVolume(5);
    tmrpcm.play((String(key) + ".wav").c_str());
  }
  digitalWrite(bluePin, LOW);
}

// Blink LED Function
void blinkLED(int pin, int duration, int repeat) {
  for (int i = 0; i < repeat; i++) {
    digitalWrite(pin, HIGH);
    delay(duration);
    digitalWrite(pin, LOW);
    delay(duration);
  }
}