//***************************************************
//
// ATtiny202 Project
// Morse Practice Sender
// XRQTechLab 202409
//
//***************************************************

const char* message1 = "ABCDE FGHIJ KLMNO PQRST UVWXY Z";
const char* message2 = "1234567890 AUV456BDNT";
const char* message3 = "TNX CU TU GL GM GA 73 ES 88 / ?";

const char* morseCode[] = {
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.",
"-..-.", // /
"..--.." // ?
};

const int ledPin = 2;
const int piezoPin = 3;
const int buttonPin = 4;
const int speedUpButtonPin = 0;
const int speedDownButtonPin = 1;
int dotDuration = 120; // 20WPM

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(piezoPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(speedUpButtonPin, INPUT_PULLUP);
pinMode(speedDownButtonPin, INPUT_PULLUP);
}

void loop() {
int buttonState = digitalRead(buttonPin);
int speedUpButtonState = digitalRead(speedUpButtonPin);
int speedDownButtonState = digitalRead(speedDownButtonPin);
static unsigned long buttonPressTime = 0;
static bool buttonPressed = false;
static unsigned long lastPressTime = 0;
static int pressCount = 0;

if (speedUpButtonState == LOW) {
dotDuration = max(40, dotDuration - 8); // 30WPM
delay(200);
}
if (speedDownButtonState == LOW) {
dotDuration = min(120, dotDuration + 8); // 10WPM
delay(200);
}

if (buttonState == LOW && !buttonPressed) {
buttonPressed = true;
buttonPressTime = millis();
}

if (buttonState == HIGH && buttonPressed) {
buttonPressed = false;
unsigned long pressDuration = millis() - buttonPressTime;

if (pressDuration < 150) {
pressCount++;
lastPressTime = millis();
} else if (pressDuration >= 700) {
sendMorse(message3);
pressCount = 0;
}
}

if (pressCount > 0 && (millis() - lastPressTime) > 400) {
if (pressCount == 1) {
sendMorse(message1);
} else if (pressCount == 2) {
sendMorse(message2);
}
pressCount = 0;
}
}

void sendMorse(const char* message) {
while (*message) {
if (*message >= 'A' && *message <= 'Z') {
const char* code = morseCode[*message - 'A'];
while (*code) {
if (*code == '.') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration);
} else if (*code == '-') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration * 3);
}
digitalWrite(ledPin, LOW);
delay(dotDuration);
code++;
}
} else if (*message >= '0' && *message <= '9') {
const char* code = morseCode[*message - '0' + 26];
while (*code) {
if (*code == '.') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration);
} else if (*code == '-') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration * 3);
}
digitalWrite(ledPin, LOW);
delay(dotDuration);
code++;
}
} else if (*message == '/') {
const char* code = morseCode[36];
while (*code) {
if (*code == '.') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration);
} else if (*code == '-') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration * 3);
}
digitalWrite(ledPin, LOW);
delay(dotDuration);
code++;
}
} else if (*message == '?') {
const char* code = morseCode[37];
while (*code) {
if (*code == '.') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration);
} else if (*code == '-') {
digitalWrite(ledPin, HIGH);
playTone(piezoPin, 1000, dotDuration * 3);
}
digitalWrite(ledPin, LOW);
delay(dotDuration);
code++;
}
} else if (*message == ' ') {
delay(dotDuration * 7);
}
delay(dotDuration * 3);
message++;
}
}

void playTone(int pin, int frequency, int duration) {
int period = 1000000L / frequency;
int pulse = period / 2;
for (long i = 0; i < duration * 1000L; i += period) {
digitalWrite(pin, HIGH);
delayMicroseconds(pulse);
digitalWrite(pin, LOW);
delayMicroseconds(pulse);
}
}