#include <Wire.h> // for working with I2C
#include <LiquidCrystal_I2C.h> // for working with the display
#define DASHBUTTONPIN 12
#define DOTBUTTONPIN 8
#define SEPBUTTONPIN 10
#define DISPLAY_NUMOFCOLUMNS 16 // Working with a 16x2 display
int dashButtonState = 0;
int dashButtonLastState = 0;
int dotButtonState = 0;
int dotButtonLastState = 0;
int sepButtonState = 0;
int sepButtonLastState = 0;
String tonesBuffer;
String text;
String expectedText;
String symbolsAlphabet[][2] =
{
{ ".-","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"}
};
LiquidCrystal_I2C lcd(0x27, DISPLAY_NUMOFCOLUMNS, 2);
char getToneFromButtonStates()
{
// Returns tone when button is released (current state is 0, previous state was 1)
if (!dashButtonState && dashButtonLastState)
return '-';
if (!dotButtonState && dotButtonLastState)
return '.';
if (!sepButtonState && sepButtonLastState)
return ' ';
return (char)0;
}
char getSymbolFromBuffer()
{
if (tonesBuffer == "")
return ' '; // Makes a space if there are no previous characters
for (int i = 0; i < sizeof symbolsAlphabet / sizeof symbolsAlphabet[0]; i++)
// Loops through all symbols and compares the buffer with the alphabet
if (tonesBuffer == symbolsAlphabet[i][0])
return symbolsAlphabet[i][1][0]; // If match found, returns the corresponding symbol
// Buffer doesn't match any symbol, return nothing
return (char)0;
}
void extractActionFromTonesBuffer()
{
if (tonesBuffer == "......") // 6x dot
text.remove(text.length() - 1, 1); // Deletes one letter
if (tonesBuffer == "------") // 6x dash
text = ""; // Deletes all text
}
void setup() {
lcd.init();
lcd.backlight();
lcd.print("Morse Notepad");
lcd.setCursor(0, 1);
lcd.print("6x-Del1 6x-Clear");
pinMode(DASHBUTTONPIN, INPUT);
pinMode(DOTBUTTONPIN, INPUT);
pinMode(SEPBUTTONPIN, INPUT);
}
void loop() {
// Reading button states
dashButtonState = digitalRead(DASHBUTTONPIN);
dotButtonState = digitalRead(DOTBUTTONPIN);
sepButtonState = digitalRead(SEPBUTTONPIN);
char tone = getToneFromButtonStates(); // Check if a button is pressed and which one
if (tone != (char)0)
{
if (tone == ' ') // Sequence of tones ends, search for a symbol
{
char symbol = getSymbolFromBuffer();
if (symbol != (char)0) // Tone sequence found a symbol, add to text
{
text += symbol;
if (text.length() > DISPLAY_NUMOFCOLUMNS) // If text exceeds display size
{
// The new symbol is written at the first position, others are erased
text = (String)symbol;
}
}
else // Tone sequence might represent an action (e.g., delete character)
{
extractActionFromTonesBuffer();
}
tonesBuffer = ""; // Clear the tone buffer (dots and dashes)
}
else // Dash or dot
{
tonesBuffer += tone;
if (tonesBuffer.length() > DISPLAY_NUMOFCOLUMNS) // If buffer exceeds display size, clear it
{
tonesBuffer = (String)tone;
}
}
// Writing to the display happens only if a button was pressed
lcd.clear(); // Clear the display
lcd.print(text); // Print the text
lcd.setCursor(0, 1);
lcd.print(tonesBuffer); // Print the tone sequence
}
// Update previous button states
dashButtonLastState = dashButtonState;
dotButtonLastState = dotButtonState;
sepButtonLastState = sepButtonState;
}