// Morse code Interpreter & Trainer
// ATMEGA328p, 16x2 lcd display
#include <Arduino.h>
#include "LiquidCrystal.h"
// For Atual hardware
// #define SW1 8
// #define SW2 5
// #define LED 2
// #define BZ 7
// For Simulation
#define SW1 5
#define SW2 7
#define LED 1
#define BZ 6
// Comst Variables
#define M_DLY 75 // Morse delay ms
#define B_DLY 250 // Button delay ms
#define N 54 // Size of array
//LiquidCrystal lcd(13, 12, 11, 10, 9, 6); //(RS, EN, D4, D5, D6, D7) // For Atual hardware
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); //(RS, EN, D4, D5, D6, D7) // For Simulation
const String KEYS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,?!'()&:;/_=+-$@ "; // Characters, Numbers & Symbols
const char *VALUES[N] = {
".-", // 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
".----", // 1
"..---", // 2
"...--", // 3
"....-", // 4
".....", // 5
"-....", // 6
"--...", // 7
"---..", // 8
"----.", // 9
"-----", // 0
".-.-.-", // .
"--..--", // ,
"..--..", // ?
"-.-.--", // !
".----.", // '
"-.--.", // (
"-.--.-", // )
".-...", // &
"---...", // :
"-.-.-.", // ;
"-..-.", // /
"..--.-", // _
"-...-", // =
".-.-.", // +
"-....-", // -
"...-..-", // $
".--.-.", // @
"|" // ' '
};
// Custom Character
unsigned const char RIGHT[8] = {0x00, 0x01, 0x03, 0x06, 0x1C, 0x08, 0x00, 0x00};
unsigned const char BLOCK[8] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
// Variables
int mode=0, test=0;
int cur=0, mks=0;
unsigned long time=0;
unsigned long start=0;
unsigned long stop=0;
bool sh_press = false;
bool press = false;
bool res = false;
String wrd, val;
char key;
char getKey(String str){
int i=0;
for(i=0; i<N; i++){
if(str == String(VALUES[i])) return KEYS[i];
}
return '\0';
}
String getVal(char ch){
int i=0;
for(i=0; i<N; i++){
if(ch == KEYS[i]) return String(VALUES[i]);
}
return "\0";
}
void turnOn(){
digitalWrite(LED, HIGH); // Turn on led
digitalWrite(BZ, HIGH); // Turn on buzzer
}
void turnOff(){
digitalWrite(LED, LOW); // Turning off led
digitalWrite(BZ, LOW); // Turning off buzzer
}
void pressed(){
turnOn();
if(!press){
start = millis();
press = true;
}
}
void released(){
turnOff();
if(press){
stop = millis();
if(stop-start >= 3*M_DLY) val += "-";
else val += ".";
press = false;
}
if(stop-millis() >= 3*M_DLY){
lcd.clear();
lcd.setCursor((wrd.length()%16)-1, 1);
if(key = getKey(val)) wrd += key;
else wrd += "";
val = "";
}
}
void setup(){
Serial.begin(9600);
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print(" Created by ");
lcd.setCursor(0,1);
lcd.print(" BHAVESH KALE ");
delay(2500);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Welcome to morse");
lcd.setCursor(0,1);
lcd.print("code interpreter");
delay(2500);
lcd.clear();
Serial.println("INSTRUCTIONS\n");
Serial.println("Type massage only upto 16 characters");
Serial.println("Then press send button and wait\n");
Serial.println("For Morse to Character");
Serial.println("1) Type your message in '.' and '-'");
Serial.println("2) For spacing wrd use '|'");
Serial.println("3) Every letter code is saperated by ' '\n");
Serial.println("For Character to Morse");
Serial.println("1) Type your message in characters\n");
pinMode(SW1, INPUT_PULLUP);
pinMode(SW2, INPUT_PULLUP);
pinMode(BZ, OUTPUT);
pinMode(LED, OUTPUT);
lcd.createChar(0, BLOCK);
lcd.createChar(1, RIGHT);
}
void loop(){
// Check switch 2 is pressed
if(!digitalRead(SW2)){ // if switch is pressed
time = millis();
while(!digitalRead(SW2)); // Until switch release
time = millis() - time;
// Check short press & long press
if(50<time && time<B_DLY) sh_press = true;
else if(2*B_DLY<time){
mode++;
if(3<mode) mode=0;
lcd.clear();
sh_press = false; wrd="";
test=0; start=0; stop=0;
}
}
// Mode Changing
if(mode==0) pract_Mode();
else if(mode==1) test_Mode();
else if(mode==2) charMorse_Mode();
else morseChar_Mode();
}
void pract_Mode(){
lcd.setCursor(0, 0);
if(wrd.length()>32) wrd.remove(0, 16);
if(wrd.length()<16) lcd.print(" Practice Mode ");
else lcd.print(wrd.substring(0, 16));
if(sh_press){
lcd.clear();
wrd = "";
sh_press = false;
}
}
void test_Mode(){
lcd.setCursor(0, 0);
lcd.print(" Test Mode ");
if(sh_press){
lcd.clear();
wrd = "";
mks=0;
test++;
if(test>9) test=0;
sh_press = false;
res = false;
}
if(test == 0) wrd = "HELLOWORLDHOWARE";
else if(test == 1) wrd = "HTDESGDTFSFIGUKL";
else if(test == 2) wrd = "OGBSWSBCLUDFVXCV";
else if(test == 3) wrd = "ZBE3W7DFG6VSKYVK";
else if(test == 4) wrd = "BV3C5SAI8G35CH95";
else if(test == 5) wrd = "C7Z3Q8W4F7G3JE3Y";
else if(test == 6) wrd = "XYT#B6%8&GD.-TS2";
else if(test == 7) wrd = "ISD6$W.,543@VJ%B";
else if(test == 8) wrd = "IHD5$@#HKJDFBV.J";
else wrd = "4CS7$S%H&!KJB9HX";
lcd.setCursor(0, 1);
if(res){
lcd.print("Res:");
lcd.print(mks);
lcd.print("/16 ");
lcd.print(mks/0.16); // mks * 100 / 16
lcd.print("%");
}
else lcd.print(wrd);
if(!digitalRead(SW1)){
mks=0;
cur=0;
while(cur<16){
if(!digitalRead(SW1)) start = millis();
if(digitalRead(SW1)) stop = millis();
}
}
}
void charMorse_Mode(){
lcd.setCursor(0, 0);
lcd.print(" Char to Morse ");
}
void morseChar_Mode(){
lcd.setCursor(0, 0);
lcd.print(" Morse to Char ");
}