//***********************************************
// CW Experience Keyer
// ATtiny 402 Project for 202&402
// XRQTechLab 2024,11,26
// Ver 005
//***********************************************

#include <avr/pgmspace.h>

const char message1[] PROGMEM = "ABCDE FGHIJ KLMNO PQRST UVWXY Z"; 裏モードメッセージ1
const char message2[] PROGMEM = "12345 67890 AUV45 6BDNT"; //裏モードメッセージ2
const char openingMessage[] PROGMEM = " XRQTECHLAB GL ";  //オープニングメッセージ

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

// フラッシュメモリから読み取るための関数
void readMessage(const char* progmemMessage, char* buffer, size_t bufferSize) {
strncpy_P(buffer, progmemMessage, bufferSize);
}

const int ledPin = 2;
const int piezoPin = 3;
const int keyPin = 4;
const int rxinPin = 0;
const int txoutPin = 1;
int dotDuration = 120; // 20WPM   //裏モード モールス符号送出スピード

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(piezoPin, OUTPUT);
pinMode(keyPin, INPUT_PULLUP);
pinMode(rxinPin, INPUT_PULLUP);
pinMode(txoutPin, OUTPUT);

char buffer[64]; // メッセージを一時的に保存するバッファ

if (digitalRead(keyPin) == LOW) {
while (true) {
readMessage(message1, buffer, sizeof(buffer));
sendMorse(buffer);
readMessage(message2, buffer, sizeof(buffer));
sendMorse(buffer);
}
} else {
int dotDuration = 80; // openingmessage speed 25WPM オープニングメッセージ スピード
readMessage(openingMessage, buffer, sizeof(buffer));
sendMorse(buffer);
}
}
void sendMorse(const char* message) {
while (*message) {
if (digitalRead(keyPin) == LOW || digitalRead(rxinPin) == LOW) return; // 優先して入力状態をチェック

if (*message >= 'A' && *message <= 'Z') {
const char* code = (const char*)pgm_read_ptr(&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 = (const char*)pgm_read_ptr(&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 = (const char*)pgm_read_ptr(&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 = (const char*)pgm_read_ptr(&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);
}
}

void loop() {                            //体験装置メインプロセス
int keyState = digitalRead(keyPin);
int rxState = digitalRead(rxinPin);

if (keyState == LOW) {
digitalWrite(txoutPin, HIGH); // TXoutをHighに
playTone2(piezoPin, 800); // 800Hzの音を出力
} else {
digitalWrite(txoutPin, LOW);
noTone2(piezoPin); // 音を止める
}

if (rxState == LOW) {
digitalWrite(ledPin, HIGH);
playTone2(piezoPin, 1000); // 1000Hzの音を出力
} else {
digitalWrite(ledPin, LOW);
noTone2(piezoPin); // 音を止める
}
}
void playTone2(int pin, int frequency ) {
int period = 1000000L / frequency;
int pulse = period / 2;
digitalWrite(pin, HIGH);
delayMicroseconds(pulse);
digitalWrite(pin, LOW);
delayMicroseconds(pulse);
}

void noTone2(int pin) {
digitalWrite(pin, LOW);
}