We made use of TextLCD library.

Dependencies:   PS2Keyboard SDFileSystem TSI TextLCD mbed

Fork of TextLCD_HelloWorld by Simon Ford

main.cpp

Committer:
Ceyhun_Emre
Date:
2018-06-02
Revision:
3:7c22a2f849c6
Parent:
2:ad0b044d0a10

File content as of revision 3:7c22a2f849c6:

#include "mbed.h"
#include "TextLCD.h"
#include "PS2ASCII.h"
#include "TSISensor.h"
#include "SDFileSystem.h"
#include <string>       //to define string
#include <vector>

// Peripheral IO initializations, the Ticker Object and global variables
TextLCD lcd(D0, D1, D2, D3, D4, D5, TextLCD::LCD20x4);
PS2ASCII ps2kb(D6, D7);
DigitalOut led(LED1);
DigitalOut buzzer(D8);
TSISensor touchSlider;
Ticker callCheckSOS;
bool stopSOS;
bool percentageNonZero;

// Screen function declarations. These functions are created to provide modularity to the code.
// They take references as inputs to modify variables declared in the main function.
void MenuScreen(int& screenValue, int& cursorIndex);
void EncodeScreen(int& screenValue, string& textToEncode, string& encodedText, vector<string>& pairToWrite);
void morseInputScreen(int& screenValue, string& morseInputText, vector<string>& pairToWrite);
void EmergencySOS(int& screenValue);
void AfterEncodeOptions(int& screenValue, int& cursorIndex, int& selectedCheckboxes, string& encodedText);
void afterMorseInputOptions(int& screenValue, int& cursorIndex, int& selectedCheckboxes, string& morseInputText, vector<string>& pairToWrite);
void writeToSDScreen(int& screenValue, vector<string>& pairToWrite, string& fileName);

// Algorithm function declarations. These functions are the backbone of the project, as they perform encode, decode & transmission tasks.
string encode (string textToEncode);
string morseInput();
string decode( string textToDecode);
char findChar( string code);
void checkSOS();
void transmitLED (string encodedText);
void transmitBuzzer (string encodedText);
void transmitLEDAndBuzzer (string encodedText);

// The main function. After performing initial tasks, it enters an infinite loop which only calls screen functions.
int main() {
    led = 1; // Turning off the led (active low)
    
    // Setting user defined characters (udc) for LCD
    const char udc_rightCursor[]     = {8, 12, 14, 15, 14, 12, 8, 0};
    const char udc_emptyCheckBox[]   = {0, 31, 17, 17, 17, 17, 31, 0};
    const char udc_fullCheckBox[] = {0, 31, 31, 31, 31, 31, 31, 0};
    
    lcd.setUDC(0, (char *) udc_rightCursor);
    lcd.setUDC(1, (char *) udc_emptyCheckBox);
    lcd.setUDC(2, (char *) udc_fullCheckBox);
    
    // Intro Screen
    lcd.setCursor(TextLCD::CurOff_BlkOff);
    lcd.printf("     Morse Code\n");
    lcd.locate(0, 1);
    lcd.printf(" Encoder - Decoder\n");
    lcd.locate(0, 2);
    lcd.printf("     Device by\n");
    lcd.locate(0, 3);
    lcd.printf("      CS & CEO\n");
    wait(3);
    
    // Variable declarations which are passed between screens (they work similar to a global variable)
    int screenValue = 0;
    int cursorIndex = 0;
    int selectedCheckboxes = 0;
    
    string textToEncode = "";
    string morseInputText = "";
    string encodedText = "";
    string decodedText = "";
    string fileName = "";
    vector<string> pairToWrite(2);
    pairToWrite[0] = "";
    pairToWrite[1] = "";
    
    // The infinite loop with only a simple switch-case block that calls screens according to the screenValue variable.
    // This variable is modified at the end of any screen function so that main program calls in appropriate screen.
    while(1) {
        lcd.cls();
        
        switch (screenValue) {
            case 0 :
                MenuScreen(screenValue, cursorIndex);
                break;
            case 1 :
                EncodeScreen(screenValue, textToEncode, encodedText, pairToWrite);
                break;
            case 2 :
                morseInputScreen(screenValue, morseInputText, pairToWrite);
                break;
            case 3 :
                EmergencySOS(screenValue);
                break;
            case 4 :
                AfterEncodeOptions(screenValue, cursorIndex, selectedCheckboxes, encodedText);
                break;
            case 5 :
                afterMorseInputOptions(screenValue, cursorIndex, selectedCheckboxes, morseInputText, pairToWrite);
                break;
            case 6 :
                writeToSDScreen(screenValue, pairToWrite, fileName);
                break;
            default :
                MenuScreen(screenValue, cursorIndex);
        }
        
    }
       
}

// This function constructs the main menu screen. Here, the user can select one of the four options to perform through a cursor interface.
// The cursor can be moved with PS/2 keyboard arrow keys and the option can be selected by pressing the Enter key.
void MenuScreen(int& screenValue, int& cursorIndex) {
    const int CURSOR_MAX_INDEX = 3;     // The constant showing the max. location of the cursor, starting from index 0.
    
    lcd.locate(0, 0);
    lcd.printf("  Encode Text\n");          // Launchs the encode screen.
    lcd.locate(0, 1);
    lcd.printf("  Input Morse Code\n");     // Launchs the Morse input screen
    lcd.locate(0, 2);
    lcd.printf("  Emergency SOS!\n");       // Launchs the emergency SOS (distress signal) screen.
    lcd.locate(0, 3);  
    lcd.printf("  Write to SD Card\n");     // Launchs the SD Card screen

    // Places the cursor to the appropriate screen. The cursor character is in the 0th custom character RAM location.
    lcd.locate(0, cursorIndex);
    lcd.putc(0x00);
    
    // Asks for keypress from the keyboard and sets the arrowValue variable to 0. 
    // Followingly, this variable is given a value of 1 or -1 according to the arrow (or 0 for other keys).   
    unsigned char pressedChar = ps2kb.getChar();
    int arrowValue = 0;
            
    if (ps2kb.E0flag() || !ps2kb.numlock()) {
        switch (pressedChar) {
            case 0x72 :
                arrowValue = 1;
                break;
            case 0x74 :
                arrowValue = 1;
                break;
            case 0x75 :
                arrowValue = -1;
                break;
            case 0x6B:
                arrowValue = -1;
                break;
            default:
                arrowValue = 0;
        }
            
            cursorIndex += arrowValue; // arrowValue is added to the cursorIndex to move the cursor on the next iteration of the screen.
            
            // Algorithm to prevent the overflow of the cursorIndex and keep it in the interval [0, CURSOR_MAX_INDEX]
            if (cursorIndex == -1)
                cursorIndex = CURSOR_MAX_INDEX;
                
            else if (cursorIndex == (CURSOR_MAX_INDEX + 1))
                cursorIndex = 0;
                    
    }
    
    // If Enter is pressed, this block sets the screenValue and clears the cursorIndex for the execution of the chosen screen.
    if (pressedChar == 0x5A) {
        switch  (cursorIndex) {
            case 0 :
                screenValue = 1;
                cursorIndex = 0;
                
                lcd.cls();
                lcd.printf("Please enter the\n");
                lcd.locate(0, 1);
                lcd.printf("text to be encoded.\n");
                lcd.locate(0, 2);
                lcd.printf("\"Enter\": Encode\n");
                lcd.locate(0, 3);
                lcd.printf("\"Esc\": Cancel\n");
                wait(3);
                
                lcd.cls();
                lcd.setCursor(TextLCD::CurOn_BlkOn);
                
                break;
                
            case 1 :
                screenValue = 2;
                cursorIndex = 0;
                break;
                
            case 2 :
                screenValue = 3;
                cursorIndex = 0;
                break;
            
            case 3:
                screenValue = 6;
                cursorIndex = 0;
                
                lcd.cls();
                lcd.printf("Please enter the\n");
                lcd.locate(0, 1);
                lcd.printf("file name.\n");
                lcd.locate(0, 2);
                lcd.printf("\"Enter\": Proceed\n");
                wait(3);
                
                lcd.cls();
                lcd.setCursor(TextLCD::CurOn_BlkOn);
                
                break;
                
            default :
                screenValue = 0;
        }
    }
}

// This function launchs the encode screen, where the user is promped to enter a text to encode, through the keyboard.
void EncodeScreen(int& screenValue, string& textToEncode, string& encodedText, vector<string>& pairToWrite) {
    lcd.cls();
    lcd.printf(textToEncode.c_str());
    unsigned char pressedChar = ps2kb.getChar();
    
    // The Esc keypress sends the user back to the menu screen.
    if (pressedChar == 0x76) {
        lcd.setCursor(TextLCD::CurOff_BlkOff);
        textToEncode = "";
        screenValue = 0;
    }
    
    // The Enter key prompts the device to take the text as the input for the encode algorithm.    
    else if (pressedChar == 0x5A) {
        
        // If nothing is entered, the user is warned to do so.
        if (textToEncode.compare("") == 0) {
            lcd.setCursor(TextLCD::CurOff_BlkOff);
            lcd.printf("Please enter a text first.\n");
            wait(2);
            lcd.setCursor(TextLCD::CurOn_BlkOn);
        }
        
        // If the user enters a text, this block calls in the encode function and moves to post-encode screen.
        else {
            screenValue = 4;
            
            encodedText = encode(textToEncode);
            pairToWrite[0] = textToEncode;
            pairToWrite[1] = encodedText;
            textToEncode = "";
            lcd.setCursor(TextLCD::CurOff_BlkOff);
            lcd.cls();
            lcd.printf("Encode Successful!\n");
            lcd.locate(0, 1);
            lcd.printf("Please check display\n");
            lcd.locate(0, 2);
            lcd.printf("and transmit options\n");
            lcd.locate(0, 3);
            lcd.printf("you want.\n");
            wait(1);
            lcd.cls();
        }
    }
    
    // If Backspace is pressed, a character is erased, unless there is nothing to erase.    
    else if (pressedChar == 0x66) {
        if (textToEncode.compare("") != 0)
            textToEncode = textToEncode.substr(0, textToEncode.length() - 1);
    }
    
    // If something else is pressed, it is appended to the textToEncode screen.
    else 
        textToEncode += ps2kb.getASCII(pressedChar);
          
 } 

// This function launches the post-encode screen where the user can choose any combination of
// transmission by LED and/or buzzer and displaying the encoded text. 
void AfterEncodeOptions(int& screenValue, int& cursorIndex, int& selectedCheckboxes, string& encodedText) {
    const int CURSOR_MAX_INDEX = 2;
    
    lcd.cls();
    lcd.printf("  Transmit Mode:\n");
    lcd.locate(2, 1);
    lcd.printf("  LED\n");
    lcd.locate(2, 2);
    lcd.printf("  Buzzer\n");
    lcd.locate(0, 3);
    lcd.printf("  Display\n");
    
    // Cursor is placed into the appropriate position, which is moved by the arrow keys.   
    lcd.locate(0, cursorIndex + 1);
    lcd.putc(0x00);
    
    // This block prints the checkboxes next to the options, either empty or full according to user's choice.   
    lcd.locate(11, 1);
    if ((selectedCheckboxes & 0x01) == 0x00)
        lcd.putc(0x01);
    else
        lcd.putc(0x02);
       
    lcd.locate(11, 2);
    if ((selectedCheckboxes & 0x02) == 0x00)
        lcd.putc(0x01);
    else
        lcd.putc(0x02);
            
    lcd.locate(11, 3);
    if ((selectedCheckboxes & 0x04) == 0x00)
        lcd.putc(0x01);
    else
        lcd.putc(0x02);
        
    unsigned char pressedChar = ps2kb.getChar();
    int arrowValue = 0;
    
    // Same arrowValue algorithm from the main menu.
    if (ps2kb.E0flag() || !ps2kb.numlock()) {
        switch (pressedChar) {
            case 0x72 :
                arrowValue = 1;
                break;
            case 0x74 :
                arrowValue = 1;
                break;
            case 0x75 :
                arrowValue = -1;
                break;
            case 0x6B:
                arrowValue = -1;
                break;
            default:
                arrowValue = 0;
        }
            
        cursorIndex += arrowValue;
            
        if (cursorIndex == -1)
            cursorIndex = 2;
                
        else if (cursorIndex == (CURSOR_MAX_INDEX + 1))
            cursorIndex = 0;
                    
    }
    
    // If Space is pressed, the device either selects or deselects the checkbox
    // depending on the previous state. This is done through the selectedCheckboxes
    // variable, which stores the states of the checkboxes in its first 3 bits.
    // The complement operation is done through bitwise AND comparison in if-else blocks
    // inside a switch-case block.
    if (pressedChar == 0x29) {
        switch (cursorIndex) {
            case 0 :
                if ((selectedCheckboxes & 0x01) == 0x00)
                    selectedCheckboxes += 1;
                else
                    selectedCheckboxes -= 1;
                break;
            case 1 :
                if ((selectedCheckboxes & 0x02) == 0x00)
                    selectedCheckboxes += 2;
                else
                    selectedCheckboxes -= 2;
                break;
            case 2 :
                if ((selectedCheckboxes & 0x04) == 0x00)
                    selectedCheckboxes += 4;
                else
                    selectedCheckboxes -= 4;
                break;
        }
    }
    
    // When Enter is pressed, the options chosen are executed.    
    else if (pressedChar == 0x5A) {
        
        // If no checkbox is selected, the user is warned.
        if (selectedCheckboxes == 0) {
            lcd.cls();
            lcd.printf("Please select at    least 1 checkbox.\n");
            wait(2);
        }
        
        else {
            lcd.cls();
            // If display option is chosen, it is executed first.
            if (selectedCheckboxes >= 4)
                lcd.printf(encodedText.c_str());
            
            // Transmit algorithms are checked and executed if selected.
            if ((selectedCheckboxes & 0x03) == 0x01)
                transmitLED(encodedText);
            else if ((selectedCheckboxes & 0x03) == 0x02)
                transmitBuzzer(encodedText);
            else if ((selectedCheckboxes & 0x03) == 0x03)
                transmitLEDAndBuzzer(encodedText);
            else
                wait(5); // Display duration when no transmit is selected.
            
            lcd.cls();
            screenValue = 0;
            cursorIndex = 0;
            selectedCheckboxes = 0;
            encodedText = "";
        }
    }
}

// This function launchs the encode screen, where the user is promped to enter a text to decode, through the
// capacitive touch slider.
void morseInputScreen(int& screenValue , string& morseInputText, vector<string>& pairToWrite) {
    // The instructions are displayed to the user, since the Morse input procedure is more
    // sophisticated than the text input.
    lcd.cls();
    lcd.printf( "Press for each\n");
    lcd.locate(0,1);
    lcd.printf( "time red led is on\n");
    wait( 3);
    lcd.cls();
    
    lcd.printf( "bottom* of slider: -\n");
    lcd.locate(0, 1);
    lcd.printf( "top* of slider: .\n");
    lcd.locate(0, 2);
    lcd.printf( ".-.-.: END\n"); // End of message sequence to end the input.
    lcd.locate(0, 3);
    lcd.printf( "*when USB is on left");
    wait( 3);
    lcd.cls();
    
    lcd.printf( "Missing 1 period:\n");
    lcd.locate(0, 1);
    lcd.printf( "space between char.s\n");
    lcd.locate(0, 2);
    lcd.printf( "Missing 2 periods:\n");
    lcd.locate(0, 3);
    lcd.printf( "space between words\n");
    wait( 3);
    lcd.cls();
    
    // Morse input algorithm is called.
    morseInputText = morseInput();
    pairToWrite[0] = morseInputText;
    screenValue = 5;
}

// This function launches the post-morse input screen where the user can choose any combination of
// transmission by LED and/or buzzer and decoding & displaying the decodec text. 
void afterMorseInputOptions(int& screenValue, int& cursorIndex, int& selectedCheckboxes, string& morseInputText, vector<string>& pairToWrite) {
    const int CURSOR_MAX_INDEX = 2;
    
    lcd.cls();
    lcd.printf("  Transmit Mode:\n");
    lcd.locate(2, 1);
    lcd.printf("  LED\n");
    lcd.locate(2, 2);
    lcd.printf("  Buzzer\n");
    lcd.locate(0, 3);
    lcd.printf("  Decode & Display\n");
    
    // Cursor is placed into the appropriate position, which is moved by the arrow keys.   
    lcd.locate(0, cursorIndex + 1);
    lcd.putc(0x00);
    
    // This block prints the checkboxes next to the options, either empty or full according to user's choice.    
    lcd.locate(11, 1);
    if ((selectedCheckboxes & 0x01) == 0x00)
        lcd.putc(0x01);
    else
        lcd.putc(0x02);
       
    lcd.locate(11, 2);
    if ((selectedCheckboxes & 0x02) == 0x00)
        lcd.putc(0x01);
    else
        lcd.putc(0x02);
            
    lcd.locate(20, 3);
    if ((selectedCheckboxes & 0x04) == 0x00)
        lcd.putc(0x01);
    else
        lcd.putc(0x02);
        
    unsigned char pressedChar = ps2kb.getChar();
    int arrowValue = 0;
    
    // Same arrowValue algorithm from the main menu.
    if (ps2kb.E0flag() || !ps2kb.numlock()) {
        switch (pressedChar) {
            case 0x72 :
                arrowValue = 1;
                break;
            case 0x74 :
                arrowValue = 1;
                break;
            case 0x75 :
                arrowValue = -1;
                break;
            case 0x6B:
                arrowValue = -1;
                break;
            default:
                arrowValue = 0;
        }
            
        cursorIndex += arrowValue;
            
        if (cursorIndex == -1)
            cursorIndex = 2;
                
        else if (cursorIndex == (CURSOR_MAX_INDEX + 1))
            cursorIndex = 0;
                    
    }
    
    // Same checkbox algorithm from the post-encode screen.
    if (pressedChar == 0x29) {
        switch (cursorIndex) {
            case 0 :
                if ((selectedCheckboxes & 0x01) == 0x00)
                    selectedCheckboxes += 1;
                else
                    selectedCheckboxes -= 1;
                break;
            case 1 :
                if ((selectedCheckboxes & 0x02) == 0x00)
                    selectedCheckboxes += 2;
                else
                    selectedCheckboxes -= 2;
                break;
            case 2 :
                if ((selectedCheckboxes & 0x04) == 0x00)
                    selectedCheckboxes += 4;
                else
                    selectedCheckboxes -= 4;
                break;
        }
    }
    
    // When Enter is pressed, the options chosen are executed.    
    else if (pressedChar == 0x5A) {
        
        // If no checkbox is selected, the user is warned.
        if (selectedCheckboxes == 0) {
            lcd.cls();
            lcd.printf("Please select at    least 1 checkbox.\n");
            wait(1);
        }
        
        else {
            // If decode & display option is chosen, it is executed first.
            lcd.cls();
            if (selectedCheckboxes >= 4) {
                string decodedText = decode( morseInputText);
                pairToWrite[1] = decodedText;
                lcd.printf(decodedText.c_str());
            }
            else
               pairToWrite[1] = ""; // Empty string is written to the SD card variable, if decode is not selected
            
            // Transmit algorithms are checked and executed if selected.
            if ((selectedCheckboxes & 0x03) == 0x01)
                transmitLED(morseInputText);
            else if ((selectedCheckboxes & 0x03) == 0x02)
                transmitBuzzer(morseInputText);
            else if ((selectedCheckboxes & 0x03) == 0x03)
                transmitLEDAndBuzzer(morseInputText);
            else
                wait(5); // Display duration when no transmit is selected.
            
            lcd.cls();
            screenValue = 0;
            cursorIndex = 0;
            selectedCheckboxes = 0;
            morseInputText = "";
        }
    }
}

// This function is called when emergency SOS screen is chosen. This screen simply transmits
// an SOS signal through LED and buzzer in an infinite loop until being interrupted by the user.
void EmergencySOS(int& screenValue){
    const string SOS_MORSE_CODE = "...---..."; // SOS Morse code string
    lcd.cls();
    lcd.printf( "Press touch slider\n");
    lcd.locate(0, 1);
    lcd.printf( "to cancel SOS signal\n");
    
    percentageNonZero = false;
    callCheckSOS.attach( &checkSOS, 0.05); // Attachs the callCheckSOS Ticker to checkSOS function
    do {
        transmitLEDAndBuzzer( SOS_MORSE_CODE);
        wait(0.75);
    } while ( !stopSOS);
    
    callCheckSOS.detach();
    lcd.cls();
    screenValue = 0;
}

// This function is called whenever the interrupt timer overflows in 50 ms. It checks the capacitive touchslider
// output. If it is different than 0 (in other words, it it is touched at least once), the stopSOS boolean is
// set true and the do while loop above is exited, which terminates the distress signal.
void checkSOS() {
    if ( !percentageNonZero && touchSlider.readPercentage() == 0) {
        stopSOS = false;
    }
    else {
        stopSOS = true;
        percentageNonZero = true;
    }
}   

// This function calls in the write-to-SD-card screen where the user can write the last
// text-Morse code pair (either encoded or decoded into the microSD card in the adapter connected to the device.
void writeToSDScreen(int& screenValue, vector<string>& pairToWrite, string& fileName) {
    SDFileSystem sdCard(D11, D12, D13, D10, "SD CARD");
    lcd.cls();
    lcd.printf(fileName.c_str());
    unsigned char pressedChar = ps2kb.getChar();
    
    // The user is promped to enter the file name.    
    if (pressedChar == 0x5A) {
        
        // The user is warned if no text is entered.
        if (fileName.compare("") == 0) {
            lcd.setCursor(TextLCD::CurOff_BlkOff);
            lcd.printf("Please enter a text first.\n");
            wait(2);
            lcd.setCursor(TextLCD::CurOn_BlkOn);
        }
        
        // Functions of the SD card library are called to write the text and morse code
        // texts into the card.
        else {
            lcd.setCursor(TextLCD::CurOff_BlkOff);
            lcd.cls();
            screenValue = 0;
            
            string fileDirectory = "/SD CARD/morse_enc_dec_dev/"; // Pre-defined directory.
            mkdir("/SD CARD/morse_enc_dec_dev", 0777);
            fileDirectory += fileName; // fileName is added to the fileDirectory.
            fileDirectory += ".txt";
            FILE *fp = fopen(fileDirectory.c_str(), "w");
            if (fp == NULL) {
                error("Could not open file for write\n");
            }
            string textToWrite = pairToWrite[0] + "   " + pairToWrite[1];
            fprintf(fp, textToWrite.c_str());
            fclose(fp);
           
            lcd.cls();
            lcd.printf("Write to SD is      successful!"); // Success message
            wait(2);
            lcd.cls();
            
            screenValue = 0;   
            fileName = "";
            lcd.setCursor(TextLCD::CurOff_BlkOff);
            
        }
    }
        
    else if (pressedChar == 0x66) {
        if (fileName.compare("") != 0)
            fileName = fileName.substr(0, fileName.length() - 1);
    }
    
    else 
        fileName += ps2kb.getASCII(pressedChar);
          
}

// This function takes text input as string and uses the binary Morse tree, coded
// in if-else blocks, to convert it to Morse code. It outputs the result as a string.
string encode( string textToEncode) {
    string encodedText = "";
    char checkedLetter;
    
    for ( short int counter = 0; counter < textToEncode.length(); counter++) {
        checkedLetter = textToEncode.at( counter);
        if ( checkedLetter == ' ') {
            encodedText += '/'; // '/' for the space between words ( 4 unit 
            // times for this char => 7 unit times for space between words)
        }
        else if ( checkedLetter == 'e' || checkedLetter == 'i' || checkedLetter == 'a'
               || checkedLetter == 's' || checkedLetter == 'u' || checkedLetter == 'r' 
               || checkedLetter == 'w' || checkedLetter == 'h' || checkedLetter == 'v' 
               || checkedLetter == 'f' || checkedLetter == 'l' || checkedLetter == 'p' 
               || checkedLetter == 'j' || checkedLetter == '5' || checkedLetter == '4' 
               || checkedLetter == '3' || checkedLetter == '2' || checkedLetter == '1' ) {
            encodedText += '.';
            if ( checkedLetter == 'i' || checkedLetter == 's' || checkedLetter == 'u'
              || checkedLetter == 'h' || checkedLetter == 'v' || checkedLetter == 'f'
              || checkedLetter == '5' || checkedLetter == '4' || checkedLetter == '3' 
              || checkedLetter == '2') {
                encodedText += '.';
                if ( checkedLetter == 's' || checkedLetter == 'h' || checkedLetter == 'v'
                  || checkedLetter == '5' || checkedLetter == '4' || checkedLetter == '3') {
                    encodedText += '.';
                    if ( checkedLetter == 'h' || checkedLetter == '5' 
                      || checkedLetter == '4') {
                        encodedText += '.';
                        if ( checkedLetter == '5') {
                            encodedText += '.';
                        }
                        else if ( checkedLetter != 'h') { // checkedLetter = '4'
                            encodedText += '-';
                        }
                    }
                    else if ( checkedLetter != 's') {
                        encodedText += '-';
                        if ( checkedLetter == '3') {
                            encodedText += '-';
                        }
                    }
                }  
                else if ( checkedLetter != 'i'){
                    encodedText += '-';
                    if ( checkedLetter == 'f') {
                        encodedText += '.';
                    }
                    else if ( checkedLetter != 'u'){ // checkedLetter = '2'
                        encodedText += "--";  
                    }
                }
            }
            else if ( checkedLetter != 'e') {
                encodedText += '-';
                if ( checkedLetter == 'r' || checkedLetter == 'l') {
                    encodedText += '.';
                    if ( checkedLetter == 'l') {
                        encodedText += '.';
                    }
                }
                else if ( checkedLetter != 'a'){
                    encodedText += '-';
                    if ( checkedLetter == 'p') {
                        encodedText += '.';
                    }
                    else if ( checkedLetter != 'w'){
                        encodedText += '-';
                        if ( checkedLetter == '1') {
                            encodedText += '-';
                        }
                    }
                }
            }
        }
        else { 
            encodedText += '-';
            if ( checkedLetter == 'n' || checkedLetter == 'd' || checkedLetter == 'k'
              || checkedLetter == 'b' || checkedLetter == 'x' || checkedLetter == 'c'
              || checkedLetter == 'y' || checkedLetter == '6') {
                encodedText += '.'; 
                if ( checkedLetter == 'd' || checkedLetter == 'b' 
                  || checkedLetter == 'x' || checkedLetter == '6') {
                    encodedText += '.';
                    if ( checkedLetter == 'b' || checkedLetter == '6') {
                        encodedText += '.';
                        if ( checkedLetter == '6') {
                            encodedText += '.';
                        }
                    }
                    else if ( checkedLetter != 'd') { //checkedLetter = 'x'
                        encodedText += '-';
                    }
                }
                else if ( checkedLetter != 'n'){
                    encodedText += '-';
                    if ( checkedLetter == 'c') {
                        encodedText += '.';
                    }
                    else if ( checkedLetter != 'k') { // checkedLetter = 'y'
                        encodedText += '-';
                    }
                }
            }
            else if ( checkedLetter != 't'){
                encodedText += '-';
                if ( checkedLetter == 'g' || checkedLetter == 'z' || checkedLetter == 'q'
                  || checkedLetter == '7') {
                    encodedText += '.';
                    if ( checkedLetter == 'z' || checkedLetter == '7') {
                        encodedText += '.';
                        if ( checkedLetter == '7') {
                            encodedText += '.';
                        }
                    }
                    else if ( checkedLetter != 'g') { // checkedLetter = 'q'
                        encodedText += '-';
                    }
                }
                else if ( checkedLetter != 'm') {
                    encodedText += '-';
                    if ( checkedLetter == '8') {
                        encodedText += "..";
                    }
                    else if ( checkedLetter != 'o'){
                        encodedText += '-';
                        if ( checkedLetter == '9') {
                            encodedText += '.';
                        }
                        else { //checkedLetter = 0 
                            encodedText += '-';
                        }
                    }
                }
            }
        }
        encodedText += ' '; // ' ' for the space between letters ( 3 unit 
        //times for this char)
    }
    return encodedText;
}

// This function is called to take Morse code input from the capacitive touchslider.
string morseInput() {
    //for taking input
    //constants
    const double unitTimeForDecoding = 1; // 250 miliseconds
    
    //variables
    string textToDecode;
    short int numberOfSpaces; // to check if a word has ended
    float currentValue;
    float pressedValue;
    string addLetter;
    bool change;
    bool takeMorseInput;
    
    //initialization
    textToDecode = "";
    numberOfSpaces = 0;
    change = true;
    takeMorseInput = true;
    
    wait( unitTimeForDecoding);
    while( takeMorseInput) {
        led = 0; //indicating that input can be taken now
        for ( short int counter = 0; counter < 200; counter++) {
            wait( unitTimeForDecoding / 200);
            if ( ( currentValue = touchSlider.readPercentage()) > 0 && change) {
                change = false;
                pressedValue = currentValue;
            }
            
            if ( touchSlider.readPercentage() == 0 && change) {
                pressedValue = 0;
            }
        }
        change = true;
        led = 1; //indicating pause
        
        if ( pressedValue <= 0) {
            addLetter = " ";
            numberOfSpaces++;
            if ( numberOfSpaces >= 2) { // seperate words
                addLetter = "/ ";
            } 
        }
        else if ( 0.5 < pressedValue && pressedValue <= 1) {
            addLetter = "-";
            numberOfSpaces = 0;
        }
        else {
            addLetter = ".";
            numberOfSpaces = 0;
        }
        textToDecode += addLetter;
        wait( unitTimeForDecoding);
        
        if ( textToDecode.length() > 6) {
            if ( ( textToDecode.substr( textToDecode.length() - 6, 6)).compare(" .-.-.") == 0) {
                takeMorseInput = false;
            }
        }
    }
    
    if ( textToDecode.at( 0) == ' ') {
        textToDecode = textToDecode.substr( (int) textToDecode.find_first_not_of( " /"), 
                                            textToDecode.length() - 6 - (int) textToDecode.find_first_not_of( " /"));
    }
    else {
        textToDecode = textToDecode.substr( 0, textToDecode.length() - 6);
    }
    return textToDecode;
}

// This function decodes the Morse code taken as a string and returns the text result as
// a string. It uses again the binary Morse code tree, coded inside the findChar function.
string decode( string textToDecode) {
    //for decoding
    //variables
    string decodedText;
    string codeForEachLetter;
    
    //initialization
    decodedText = "";
    codeForEachLetter = "";
    
    // decodes all characters other than the last one
    while ( textToDecode.find( " ") != std::string::npos) {
        codeForEachLetter = textToDecode.substr(0, textToDecode.find( " ")); 
        decodedText += findChar( codeForEachLetter);
        textToDecode = textToDecode.substr( textToDecode.find( " ") + 1, 
                                            textToDecode.length() 
                                            - ( textToDecode.find( " ") + 1));
    }
    //decodes the last character
    decodedText += findChar( textToDecode);
    
    return decodedText;
    
}

//This function performs the conversion to character while decoding. It is based
//on binary Morse code tree.
char findChar( string code) {
    if ( code.at( 0) == '.') {
        if ( code.length() != 1) {
            if ( code.at( 1) == '.') {
                if ( code.length() != 2) {
                    if ( code.at( 2) == '.') {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                if ( code.length() != 4) {
                                    if ( code.at( 4) == '.') {
                                        return '5';
                                    }
                                    return '4';
                                }
                                return 'H';
                            }
                            else {
                                if ( code.length() != 4) {
                                    return '3';
                                }
                                return 'V';
                            }
                        }
                        return 'S';
                    }
                    else {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                return 'F';
                            }
                            return '2';
                        }
                        return 'U';
                    }
                }
                return 'I';
            }
            else {
                if ( code.length() != 2) {
                    if ( code.at( 2) == '.') {
                        if ( code.length() != 3) {
                            return 'L';
                        }
                        return 'R';
                    }
                    else {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                return 'P';
                            }
                            if ( code.length() != 4) {
                                return '1';
                            }
                            return 'J';
                        }
                        return 'W';
                    }
                }
                return 'A';
            }
        }
        return 'E';
    }
    else if ( code.at( 0) == '-') {
        if ( code.length() != 1) {
            if ( code.at( 1) == '.') {
                if ( code.length() != 2) {
                    if ( code.at( 2) == '.') {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                if ( code.length() != 4) {
                                    return '6';
                                }
                                return 'B';
                            }
                            return 'X';
                        }
                        return 'D';
                    }
                    else {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                return 'C';
                            }
                            return 'Y';
                        }
                        return 'K';
                    }
                }
                return 'N';
            }
            else {
                if ( code.length() != 2) {
                    if ( code.at( 2) == '.') {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                if ( code.length() != 4) {
                                    return '7';
                                }
                                return 'Z';
                            }
                            return 'Q';
                        }
                        return 'G';
                    }
                    else {
                        if ( code.length() != 3) {
                            if ( code.at( 3) == '.') {
                                return '8';
                            }
                            if ( code.at( 4) == '.') {
                                return '9';
                            }
                            return '0';
                        }
                        return 'O';
                    }
                }
                return 'M';
            }
        }
        return 'T';
    }
    return ' '; // codeForEachLetter.at( 0) = '/'
}

// This function transmit the inputted Morse code through LED and buzzer simultaneously.
void transmitLEDAndBuzzer (string encodedText) {
    const double unitTime = 0.25; // 250 miliseconds
    
    // code to send encodedText to LED and buzzer appropriately 
    for ( short int counter = 0; counter < encodedText.length(); counter++) {
        char checkedChar = encodedText.at( counter);
        if ( checkedChar == '.') {
            led = 0;
            buzzer = 1;
            wait( unitTime);
            led = 1;
            buzzer = 0;
            wait( unitTime);
        }
        else if ( checkedChar == '-') {
            led = 0;
            buzzer = 1;
            wait( unitTime * 3);
            led = 1;
            buzzer = 0;
            wait( unitTime);
        }
        else if ( checkedChar == ' ') {
            wait( unitTime * 3);
        }
        else { // checkedChar = '/'
            wait( unitTime);
        }
    }
}

// This function transmit the inputted Morse code through only LED.
void transmitLED (string encodedText) {
    const double unitTime = 0.25; // 250 miliseconds
    
    // code to send encodedText to LED appropriately 
    for ( short int counter = 0; counter < encodedText.length(); counter++) {
        char checkedChar = encodedText.at( counter);
        if ( checkedChar == '.') {
            led = 0;
            wait( unitTime);
            led = 1;
            wait( unitTime);
        }
        else if ( checkedChar == '-') {
            led = 0;
            wait( unitTime * 3);
            led = 1;
            wait( unitTime);
        }
        else if ( checkedChar == ' ') {
            wait( unitTime * 3);
        }
        else { // checkedChar = '/'
            wait( unitTime);
        }
    }
}

// This function transmit the inputted Morse code through only buzzer.
void transmitBuzzer (string encodedText) {
    const double unitTime = 0.25; // 250 miliseconds
    
    // code to send encodedText to buzzer appropriately 
    for ( short int counter = 0; counter < encodedText.length(); counter++) {
        char checkedChar = encodedText.at( counter);
        if ( checkedChar == '.') {
            buzzer = 1;
            wait( unitTime);
            buzzer = 0;
            wait( unitTime);
        }
        else if ( checkedChar == '-') {
            buzzer = 1;
            wait( unitTime * 3);
            buzzer = 0;
            wait( unitTime);
        }
        else if ( checkedChar == ' ') {
            wait( unitTime * 3);
        }
        else { // checkedChar = '/'
            wait( unitTime);
        }
    }
}