/*
Project: MorsePractice DitDah v1a
Project by: Jim F, Calgary AB
Date Started: 2025-09-26
Date Updated: 2025-09-26
References:
https://morsecode.world/
*/
// Global Constants
const String morsePlain[] = {"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",
"'","\"","@",")",":",";",",","!",".","-","?","$","/","_","<AA>","<AR/+>",
"<AS/&>","<BK>","<BT/=>","<CL>","<CT>","<DO>","<HH>","<KN/(>","<SK>","<SN>","<SOS>"};
const byte morseCode[][9]={ // 1 = dot, 2 = dash, 0 = not used
{1,2,0,0,0,0,0,0,0}, // A .-
{2,1,1,1,0,0,0,0,0}, // B -...
{2,1,2,1,0,0,0,0,0}, // C -.-.
{2,1,1,0,0,0,0,0,0}, // D -..
{1,0,0,0,0,0,0,0,0}, // E .
{1,1,2,1,0,0,0,0,0}, // F ..-.
{2,2,1,0,0,0,0,0,0}, // G --.
{1,1,1,1,0,0,0,0,0}, // H ....
{1,1,0,0,0,0,0,0,0}, // I ..
{1,2,2,2,0,0,0,0,0}, // J .---
{2,1,2,0,0,0,0,0,0}, // K -.-
{1,2,1,1,0,0,0,0,0}, // L .-..
{2,2,0,0,0,0,0,0,0}, // M --
{2,1,0,0,0,0,0,0,0}, // N -.
{2,2,2,0,0,0,0,0,0}, // O ---
{1,2,2,1,0,0,0,0,0}, // P .--.
{2,2,1,2,0,0,0,0,0}, // Q --.-
{1,2,1,0,0,0,0,0,0}, // R .-.
{1,1,1,0,0,0,0,0,0}, // S ...
{2,0,0,0,0,0,0,0,0}, // T -
{1,1,2,0,0,0,0,0,0}, // U ..-
{1,1,1,2,0,0,0,0,0}, // V ...-
{1,2,2,0,0,0,0,0,0}, // W .--
{2,1,1,2,0,0,0,0,0}, // X -..-
{2,1,2,2,0,0,0,0,0}, // Y -.--
{2,2,1,1,0,0,0,0,0}, // Z --..
{2,2,2,2,2,0,0,0,0}, // 0 -----
{1,2,2,2,2,0,0,0,0}, // 1 .----
{1,1,2,2,2,0,0,0,0}, // 2 ..---
{1,1,1,2,2,0,0,0,0}, // 3 ...--
{1,1,1,1,2,0,0,0,0}, // 4 ....-
{1,1,1,1,1,0,0,0,0}, // 5 .....
{2,1,1,1,1,0,0,0,0}, // 6 -....
{2,2,1,1,1,0,0,0,0}, // 7 --...
{2,2,2,1,1,0,0,0,0}, // 8 ---..
{2,2,2,2,1,0,0,0,0}, // 9 ----.
{1,2,2,2,2,1,0,0,0}, // ' Apostrophe .----.
{1,2,1,1,2,1,0,0,0}, // " Quotation mark .-..-.
{1,2,2,1,2,1,0,0,0}, // @ At sign .--.-.
{2,1,2,2,1,2,0,0,0}, // ) Bracket, close (parenthesis) -.--.-
{2,2,2,1,1,1,0,0,0}, // : Colon ---...
{2,1,2,1,2,1,0,0,0}, // ; Semicolon -.-.-.
{2,2,1,1,2,2,0,0,0}, // , Comma --..--
{2,1,2,1,2,2,0,0,0}, // ! Exclamation mark -.-.--
{1,2,1,2,1,2,0,0,0}, // . Full-stop .-.-.-
{2,1,1,1,1,2,0,0,0}, // - Hyphen / Minus -....-
{1,1,2,2,1,1,0,0,0}, // ? Question mark ..--..
{1,1,1,2,1,1,2,0,0}, // $ Dollar sign ...-..-
{2,1,1,2,1,0,0,0,0}, // / Slash/Franction -..-.
{1,1,2,2,1,2,0,0,0}, // _ Underscore ..--.-
{1,2,1,2,0,0,0,0,0}, // <AA> New line .-.-
{1,2,1,2,1,0,0,0,0}, // <AR/+> End of message OR + .-.-.
{1,2,1,1,1,0,0,0,0}, // <AS/&> Wait OR & .-...
{2,1,1,1,2,1,2,0,0}, // <BK> Break -...-.-
{2,1,1,1,2,0,0,0,0}, // <BT/=> New paragraph, Break OR = -...-
{2,1,2,1,1,2,1,1,0}, // <CL> Going off the air ("clear") -.-..-..
{2,1,2,1,2,0,0,0,0}, // <CT> Start copying -.-.-
{2,1,1,2,2,2,0,0,0}, // <DO> Change to wabun code -..---
{1,1,1,1,1,1,1,1,0}, // <HH> Error ........
{2,1,2,2,1,0,0,0,0}, // <KN/(> Invite a specific station to transmit OR ( -.--.
{1,1,1,2,1,2,0,0,0}, // <SK> End of transmission ...-.-
{1,1,1,2,1,0,0,0,0}, // <SN> Understood (also VE) ...-.
{1,1,1,2,2,2,1,1,1}, // <SOS> Distress message ...---...
};
// Global Variables
int idx1=0;
int maxIdx=63;
int spkrPin=11;
int ledPin=13;
int unitDelay=250;
int keyButton=2;
unsigned long downTimer=0;
unsigned long upTimer=0;
// Setup
void setup() {
pinMode(keyButton,INPUT_PULLUP);
pinMode(spkrPin,OUTPUT);
pinMode(ledPin,OUTPUT);
Serial.begin(9600);
Serial.println("\n===BEGIN===\n");
delay(1000);
}
// Functions
void doDit() {
Serial.print("dit ");
tone(spkrPin,440);
digitalWrite(ledPin,HIGH);
delay(unitDelay);
noTone(spkrPin);
digitalWrite(ledPin,LOW);
delay(unitDelay);
}
void doDah() {
Serial.print("dah ");
tone(spkrPin,440);
digitalWrite(ledPin,HIGH);
delay(unitDelay*3);
noTone(spkrPin);
digitalWrite(ledPin,LOW);
delay(unitDelay);
}
void charToMorse(int idx) {
Serial.println("");
Serial.print(morsePlain[idx]);
Serial.print(" ");
for (int i=0; i<8; i++) {
int val=morseCode[idx][i];
if(val==1) {doDit();}
if(val==2) {doDah();}
}
Serial.println("");
}
int findString(String sch) {
for(int i=0; i<maxIdx; i++) {
if(sch==morsePlain[i]) {
return i;
}
}
return -1;
}
void stringToMorse(String code) {
code.toUpperCase();
for(int i=0; i<code.length(); i++) {
char ch=code.charAt(i);
int zz=findString(String(ch));
if(zz==-1) {
delay(unitDelay*3);
Serial.println("");
}
if(zz>-1) {
charToMorse(zz);
}
}
}
// Main Loop
void loop() {
while(Serial.available()) {
String code=Serial.readString();
stringToMorse(code);
delay(unitDelay*3);
}
if(digitalRead(keyButton)==LOW) {
digitalWrite(ledPin,HIGH);
tone(spkrPin,440);
if(downTimer==0) {downTimer=millis();}
}
if(digitalRead(keyButton)==HIGH) {
digitalWrite(ledPin,LOW);
noTone(spkrPin);
if(downTimer>0) {
unsigned long timerLen=millis()-downTimer;
Serial.println(timerLen);
downTimer=0;
}
}
delay(1);
}