const int speakerPin = 9;
const int ledPin = 11;

int elapsedSecondsState;
unsigned long lastMillisStates;
unsigned long lastMillisSerial;


const int dotDuration = 100;
const int dashDuration = 3 * dotDuration;

// Tabella di codifica Morse
const char* morseCode[] = {
  ".-",    // 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
  "-----", // 0
  ".----", // 1
  "..---", // 2
  "...--", // 3
  "....-", // 4
  ".....", // 5
  "-....", // 6
  "--...", // 7
  "---..", // 8
  "----.", // 9
  ".-.-.-",// .
  "--..--",// ,
  "..--..",// ?
  "-.-.--",// !
  "-....-",// -
  "-..-.", // /
  ".--.-.",// @
  ".-.-"   // +
};

void setup() {
  DDRB |= (1 << DDB1) | (1 << DDB3);
  Serial.begin(9600);
  elapsedSecondsState = 0;
  lastMillisStates = millis();
  lastMillisSerial = millis();
}

void loop() {
  unsigned long now = millis();

  if (Serial.available() > 0) {
    String input = Serial.readString();
    encodeMorse(input);
  }
}

void encodeMorse(const String& message) {
  unsigned long previousTime = 0;
  boolean isSpace = true;

  for (int i = 0; i < message.length(); i++) {
    char ch = toupper(message.charAt(i));

    if (ch == ' ' || ch == '\0') {
      if (!isSpace) {
        while (millis() - previousTime < dotDuration * 3) {
          // Aspetta la fine del carattere o della parola precedente
        }
        isSpace = true;
      }
      if (ch == ' ') {
        continue;
      }
    } else {
      isSpace = false;
    }

    int index = getMorseIndex(ch);
    if (index != -1) {
      generateSignal(morseCode[index]);
      previousTime = millis();

      // Aspetta l'intervallo tra i caratteri
      while (millis() - previousTime < dashDuration) {
        // Aspetta la fine del carattere attuale
      }
    }
  }
}

int getMorseIndex(char ch) {
  if (ch >= 'A' && ch <= 'Z') {
    return ch - 'A';
  } else if (ch >= '0' && ch <= '9') {
    return ch - '0' + 26;
  } else {
    switch (ch) {
      case '.':
        return 36;
      case ',':
        return 37;
      case '?':
        return 38;
      case '!':
        return 39;
      case '-':
        return 40;
      case '/':
        return 41;
      case '@':
        return 42;
      case '+':
        return 43;
      default:
        return -1;
    }
  }
}
void generateSignal(const char* code) {
  unsigned long previousTime = millis();

  for (int i = 0; code[i] != '\0'; i++) {
    switch (code[i]) {
      case '.':
        PORTB |= (1 << PORTB3);
        analogWrite(speakerPin, 100); // Durata del punto

        while (millis() - previousTime < dotDuration) {
        }

        PORTB &= ~(1 << PORTB3);
        analogWrite(speakerPin, 0);

        break;
      case '-':
        PORTB |= (1 << PORTB3);
        analogWrite(speakerPin, 300); // Durata della linea
        
        while (millis() - previousTime < dashDuration) {
        }

        PORTB &= ~(1 << PORTB3);
        analogWrite(speakerPin, 0);

        break;
    }

    // Aspetta l'intervallo tra i toni Morse
    while (millis() - previousTime < dotDuration * 4) {
    }

    previousTime = millis(); // Aggiorna il tempo dopo il completamento di un carattere
  }
}
$abcdeabcde151015202530fghijfghij