#include <LiquidCrystal.h>

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
const int ledPin = 8;
const int buttonPin = 9;

int inputCol = 7;   // Start after "Input: "
int outputCol = 8;  // Start after "Output: "
String outputText = "";  // Store all decoded letters


LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

unsigned long dotDuration = 0;
unsigned long dashDuration;
unsigned long nextCharDuration;
unsigned long spaceDuration;

unsigned long startTime;
unsigned long pressTime;
unsigned long releaseTime;

String currentMorse = "";

// Morse table
struct MorseMap {
  const char* code;
  char letter;
};

MorseMap morseTable[] = {
  {".-", 'A'},   {"-...", 'B'}, {"-.-.", 'C'}, {"-..", 'D'}, {".", 'E'},
  {"..-.", 'F'}, {"--.", 'G'},  {"....", 'H'}, {"..", 'I'},  {".---", 'J'},
  {"-.-", 'K'},  {".-..", 'L'}, {"--", 'M'},   {"-.", 'N'},  {"---", 'O'},
  {".--.", 'P'}, {"--.-", 'Q'}, {".-.", 'R'},  {"...", 'S'}, {"-", 'T'},
  {"..-", 'U'},  {"...-", 'V'}, {".--", 'W'},  {"-..-", 'X'}, {"-.--", 'Y'},
  {"--..", 'Z'}
};

char decodeMorse(String code) {
  for (int i = 0; i < 26; i++) {
    if (code == morseTable[i].code) {
      return morseTable[i].letter;
    }
  }
  return '?';
}

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);

  lcd.begin(16, 2);
  lcd.print("Press 3 dots.");

  unsigned long totalDuration = 0;

  // --- Calibration ---
  for (int i = 0; i < 3; i++) {

    while (digitalRead(buttonPin) == LOW);
    digitalWrite(ledPin, HIGH);
    startTime = millis();

    while (digitalRead(buttonPin) == HIGH);
    digitalWrite(ledPin, LOW);

    pressTime = millis() - startTime;
    totalDuration += pressTime;
  }

  dotDuration = totalDuration / 3;
  dashDuration = dotDuration * 3;
  nextCharDuration = dotDuration * 3;
  spaceDuration = dotDuration * 7;

  lcd.clear();
  lcd.print("Input:");
  lcd.setCursor(0, 1);
  lcd.print("Output:");
}

void loop() {

  if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);
    startTime = millis();

    while (digitalRead(buttonPin) == HIGH);

    digitalWrite(ledPin, LOW);
    pressTime = millis() - startTime;

    // Add dot or dash to Morse input
    lcd.setCursor(inputCol, 0);
    if (pressTime < dashDuration) {
        lcd.print(".");
        currentMorse += ".";
    } else {
        lcd.print("-");
        currentMorse += "-";
    }
    inputCol++;  // Move cursor forward
    releaseTime = millis();
  }

  // Detect gaps
  if (currentMorse.length() > 0) {
      unsigned long gapTime = millis() - releaseTime;

    // End of character
    if (gapTime > nextCharDuration && gapTime < spaceDuration) {
        char decoded = decodeMorse(currentMorse);
        outputText += decoded;

        lcd.setCursor(outputCol, 1);
        lcd.print(decoded);
        outputCol++;  // Move cursor forward

        currentMorse = "";
    }

    // Word space
    if (gapTime >= spaceDuration) {
        outputText += " ";

        lcd.setCursor(outputCol, 1);
        lcd.print(" ");
        outputCol++;

        currentMorse = "";
    }
  }
}