Morse Code Encode/Decoder

Hi Im fairly new to Arduino and stuff but i have to encode and decode morse for an assignment. Basically the input and output both have to be on the serial port. I have managed to encode the text into morse but i have no idea how i would go about decoding morse to text?

I also have a function that detects whether the first character in the string is a morse character or not to be able to use the appropriate function.

#char morse_a[] = ".-";
char morse_b[] = "-...";
char morse_c[] = "-.-.";
char morse_d[] = "-..";
char morse_e[] = ".";
char morse_f[] = "..-.";
char morse_g[] = "--.";
char morse_h[] = "....";
char morse_i[] = "..";
char morse_j[] = ".---";
char morse_k[] = "-.-";
char morse_l[] = ".-..";
char morse_m[] = "--";
char morse_n[] = "-.";
char morse_o[] = "---";
char morse_p[] = ".--.";
char morse_q[] = "--.-";
char morse_r[] = ".-.";
char morse_s[] = "...";
char morse_t[] = "-";
char morse_u[] = "..-";
char morse_v[] = "...-";
char morse_w[] = ".--";
char morse_x[] = "-..-";
char morse_y[] = "-.--";
char morse_z[] = "--..";

String morseCode;

void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
while (Serial.available() == 0) {

}
Serial.println("This is your Encoded/Decoded output:");
morseCode = Serial.readString();
printmorse (morseCode);
}

//Detects whether the first character entered is either a morse or an Ascii
void morseorAscii (String s) {
if ((s.charAt(0) == ' ') && ((s.charAt(0) == '^') || (s.charAt(0) == '=') || (s.charAt(0) == '$'))) //If the start of the string has a space and ^ or = or $ then print ASCII
{
// printAscii(s); // Decode the morse by printing Ascii
}
else { // Anything else apart from those values then print morse
printmorse(s); // Encode the Ascii my printing morse
}
}

// Encodes the Ascii text to morse
void printmorse(String s) {

for (int i = 0; i < s.length(); i++) { // goes through each character one at a time
if (s.charAt(i) == ' ') { // if the string then has a space
Serial.print(" "); // then a space will be printed
}
else {
Serial.print(ascii2morse(s*)); // print out the translation from the ascii to morse*

  • if (i == s.length() - 1) { // if we have arrived at out last character in the string we don't want anymore slashes*
  • }*
  • else if (s.charAt(i + 1) == ' ') { // if the next character is a space don't print a slash*
  • ;*
  • } else {*
  • Serial.print('/'); // print the slash to divide each morse*
  • }*
  • }*
  • }*
    }
    //void printAscii(String s) {
    //
    // if ((s.charAt(0) == '^') || (s.charAt(0) == '=') || (s.charAt(0) == '$')) {
    // Serial.print(morse2ascii(printmorse));
    // {
    // if
    // ((s.charAt(1) == '^') || (s.charAt(1) == '=') || (s.charAt(1) == '$'))
    // Serial.print(morse2ascii(printmorse));
    // {
    // if
    // ((s.charAt(2) == '^') || (s.charAt(2) == '=') || (s.charAt(2) == '$'))
    // Serial.print(morse2ascii(printmorse));
    // {
    // if
    // ((s.charAt(3) == '^') || (s.charAt(3) == '=') || (s.charAt(3) == '$'))
    // Serial.print(morse2ascii(printmorse));
    // {
    // if
    // ((s.charAt(4) == '^') || (s.charAt(4) == '=') || (s.charAt(4) == '$'))
    // Serial.print(morse2ascii(printmorse));
    // }
    // }
    // }
    // }
    // }
    //}
    // Returns the morse of the Ascii that is entered
    char * ascii2morse(char c) {
  • c = tolower (c); // Lowers the letters to be read by the code*
  • switch (c) {*
  • case 'a': return morse_a; // If the letter A is entered then return morse code for A*
  • case 'b': return morse_b; // If the letter B is entered then return morse code for B*
  • case 'c': return morse_c; // etc*
  • case 'd': return morse_d;*
  • case 'e': return morse_e;*
  • case 'f': return morse_f;*
  • case 'g': return morse_g;*
  • case 'h': return morse_h;*
  • case 'i': return morse_i;*
  • case 'j': return morse_j;*
  • case 'k': return morse_k;*
  • case 'l': return morse_l;*
  • case 'm': return morse_m;*
  • case 'n': return morse_n;*
  • case 'o': return morse_o;*
  • case 'p': return morse_p;*
  • case 'q': return morse_q;*
  • case 'r': return morse_r;*
  • case 's': return morse_s;*
  • case 't': return morse_t;*
  • case 'u': return morse_u;*
  • case 'v': return morse_v;*
  • case 'x': return morse_x;*
  • case 'y': return morse_y;*
  • case 'z': return morse_z;*
    }
    }
    // Prints each morse code as an Ascii character
    void morse2ascii (String Stringmorse){
  • if (Stringmorse == morse_a) { // If the morse code of A is entered, print the letter A*
  • Serial.print("a");*
  • }*
  • if (Stringmorse == morse_b) { // If the morse code of B is entered, print the letter B*
  • Serial.print("b");*
  • }*
  • if (Stringmorse == morse_c) { // etc*
  • Serial.print("c");*
  • }*
  • if (Stringmorse == morse_d) {*
  • Serial.print("d");*
  • }*
  • if (Stringmorse == morse_e) {*
  • Serial.print("e");*
  • }*
  • if (Stringmorse == morse_f) {*
  • Serial.print("f");*
  • }*
  • if (Stringmorse == morse_g) {*
  • Serial.print("g");*
  • }*
  • if (Stringmorse == morse_h) {*
  • Serial.print("h");*
  • }*
  • if (Stringmorse == morse_i) {*
  • Serial.print("i");*
  • }*
  • if (Stringmorse == morse_j) {*
  • Serial.print("j");*
  • }*
  • if (Stringmorse == morse_k) {*
  • Serial.print("k");*
  • }*
  • if (Stringmorse == morse_l) {*
  • Serial.print("l");*
  • }*
  • if (Stringmorse == morse_m) {*
  • Serial.print("m");*
  • }*
  • if (Stringmorse == morse_n) {*
  • Serial.print("n");*
  • }*
  • if (Stringmorse == morse_o) {*
  • Serial.print("o");*
  • }*
  • if (Stringmorse == morse_p) {*
  • Serial.print("p");*
  • }*
  • if (Stringmorse == morse_q) {*
  • Serial.print("q");*
  • }*
  • if (Stringmorse == morse_r) {*
  • Serial.print("r");*
  • }*
  • if (Stringmorse == morse_s) {*
  • Serial.print("s");*
  • }*
  • if (Stringmorse == morse_t) {*
  • Serial.print("t");*
  • }*
  • if (Stringmorse == morse_u) {*
  • Serial.print("u");*
  • }*
  • if (Stringmorse == morse_v) {*
  • Serial.print("v");*
  • }*
  • if (Stringmorse == morse_w) {*
  • Serial.print("w");*
  • }*
  • if (Stringmorse == morse_x) {*
  • Serial.print("x");*
  • }*
  • if (Stringmorse == morse_y) {*
  • Serial.print("y");*
  • }*
  • if (Stringmorse == morse_z) {*
  • Serial.print("z");*
  • }*
    }
    void loop() {
  • // put your main code here, to run repeatedly:*
    }

First, welcome to the Forum. Also, please read the two post by Nick Gammon at the top of the Forum for guidelines on using the Forum, especially the use of code tags when posting code.

Next, there have been many Morse code discussions here and you can search for those using the Search box you see at the top of the Forum header. One example:

http://forum.arduino.cc/index.php?topic=284639.5

This posts discusses some easier ways to tackle the problem.

W8TEE

Ok will do and thanks ill take a look!

@Gaddsy, Please modify your post and use the code button </>

so your code looks like this

and is easy to copy to a text editor. See How to use the Forum

...R

 if ((s.charAt(0) == ' ') && ((s.charAt(0) == '^') || (s.charAt(0) == '=') || (s.charAt(0) == '

If the first character is a space and the first character is a '^', '=', or '$', then...

What are the odds that the first character will be a space AND a $? A space AND a ^?))) //If the start of the string has a space and ^ or = or $ then print ASCII


If the first character is a space and the first character is a '^', '=', or '$', then...

What are the odds that the first character will be a space AND a $? A space AND a ^?

Gaddsy:
I have managed to encode the text into morse but i have no idea how i would go about decoding morse to text?

I also have a function that detects whether the first character in the string is a morse character or not to be able to use the appropriate function.

I'd like to suggest, that you use for coding and decoding the same type of dash/dot protocol for ASCII-conversion, i.e. like that:

  • one character is encoded with its dashs and dots and followed by a single space character (inter-character pause)
  • spaces between words are encoded as more than one (perhaps three) consecutive space characters

If you then send a string like that from the Serial monitor:

- .... .. ...   .. ...   -. .-. -.. ..- .. -. ---   ... . -. -.. .. -. --.   -- --- .-. ... .   -.-. --- -.. .

you should be able to detect what you want:
dashs and dots following each other directly ==> morse character
one space character ==> seperator between two morse characters
three space characters ==> seperator between two encoded words

While not directly usable, as this is, as you said, an assignment, is something I wrote a while back.

It's written as UNIX console app in an Arduino style.

It takes a string, pulls it apart character-by-character to lookup a encode morse character equivalent.

The encoded morse is then sent to a decoder where it is pulled apart into its component did/dahs to the console as '.', '-' with appropriate spacing.

This version is reduced from a larger application that allowed signaling to other output devices complete with word-per-minute speed adjustments for non-terminal signaling devices.

It should be fairly trivial to take the output re-encode it and lookup the character it represents.

Posted for the ideas involved in the hopes it night be helpful but without doing your assignment for you.

//  MorseIt.cpp
//  MorseEncodingTest
//
//  9/27/09.
//
//  Since I'm using the code on compiler's that support the GNU 'switch/case"
//  extensions I use the '...' case form.
//
// Test as a console application under Mac OS
//
// Make use of bit-fields, and ternary-operators


#include <iostream>
#include <sys/time.h>

unsigned long millis()
{
    timeval     tv;
    gettimeofday(&tv, NULL);
    
    return (((tv.tv_sec * 1000000) + tv.tv_usec) / 1000);
}

void delay(unsigned long const msDelay)
{
    for ( unsigned long ms = millis() + msDelay; ((long)(millis() - ms) < 0); )
    {   }
}

struct morse_encoding_t
{
    // ENCODE MORSE ELEMENT COUNT AND ELEMENT TYPES
    // WITHIN SINGLE UNSIGNED BYTE
    // 3 BITS FOR ELEMENT COUNT
    // 5 BITS FOR ARRAY OF MORSE ELEMENTS ENCODED AS SINGLE BITS IN MSB -> LSB ORDER
    //      0 = DIT, 1 = DAH
    
    uint8_t count: 3;
    uint8_t elements: 5;
};

morse_encoding_t char2encoding(char ch)
{
    const morse_encoding_t em_alpha[] =
    {
          { 2, 0b01    }    // A  .-
        , { 4, 0b1000  }    // B  -...
        , { 4, 0b1010  }    // C  -.-.
        , { 3, 0b100   }    // D  -..
        , { 1, 0b0     }    // E  .
        , { 4, 0b0010  }    // F  ..-.
        , { 3, 0b110   }    // G  --.
        , { 4, 0b0000  }    // H  ....
        , { 2, 0b00    }    // I  ..
        , { 4, 0b0111  }    // J  .---
        , { 3, 0b101   }    // K  -.-
        , { 4, 0b0100  }    // L  .-..
        , { 2, 0b11    }    // M  --
        , { 2, 0b10    }    // N  -.
        , { 3, 0b111   }    // O  ---
        , { 4, 0b0110  }    // P  .--.
        , { 4, 0b1101  }    // Q  --.-
        , { 3, 0b010   }    // R  .-.
        , { 3, 0b000   }    // S  ...
        , { 1, 0b1     }    // T  -
        , { 3, 0b001   }    // U  ..-
        , { 4, 0b0001  }    // V  ...-
        , { 3, 0b011   }    // W  .--
        , { 4, 0b1001  }    // X  -..-
        , { 4, 0b1011  }    // Y  -.--
        , { 4, 0b1100  }    // Z  --..
    };
    
    const morse_encoding_t em_numeric[] =
    {
        // --- NUMERIC
          { 5, 0b11111 }    // 0  -----
        , { 5, 0b01111 }    // 1  .----
        , { 5, 0b00111 }    // 2  ..---
        , { 5, 0b00011 }    // 3  ...--
        , { 5, 0b00001 }    // 4  ....-
        , { 5, 0b00000 }    // 5  .....
        , { 5, 0b10000 }    // 6  -....
        , { 5, 0b11000 }    // 7  --...
        , { 5, 0b11100 }    // 8  ---..
        , { 5, 0b11110 }    // 9  ----.
    };
    
    switch ( ch )
    {
        case 'a' ... 'z': return em_alpha[ch - 'a'];
        case 'A' ... 'Z': return em_alpha[ch - 'A'];
        case '0' ... '9': return em_numeric[ch - '0'];
        case '/':         return { 5, 0b10010 };
    }
    
    return { 0, 0 };
}

enum { DIT = 1, DAH = 3, INTRA_CHAR_GAP = 1, CHAR_GAP = 3, WORD_GAP = 7 };

/* Calculating Morse Code Speed
 *
 * The word PARIS is the standard for determing CW code speed. Each DOT is one
 * time unit, each DASH is three time units, intra-character spacing is one time
 * unit, inter-character spacing is three time units and inter-word spacing is
 * seven time units. The word PARIS is exactly 50 time unit.
 *
 * Note that after each DOT/DASH of the letter P -- one time unit spacing is
 * used except the last one. (Intra-Character).
 *
 * After the last DOT of P is sent, 3 time units are added (Inter-Character).
 *
 * After the word PARIS - 7 time-units are used.
 *
 * Calculateed as:
 *
 *    P = DOT DASH DASH DOT = 1 1 3 1 3 1 1 (3) = 14 time-units
 *    A = DOT DASH          = 1 1 3         (3) =  8 time-units
 *    R = DOT DASH DOT      = 1 1 3 1 1     (3) = 10 time-units
 *    I = DOT DOT           = 1 1 1         (3) =  6 time-units
 *    S = DOT DOT DOT       = 1 1 1 1 1     [7] = 12 time-units
 *    --------------------------------------------------------
 *                                                 = 50 time-units
 *
 * () = intercharacter
 * [] = interword
 *
 * If you send PARIS 5 times in a minute (5 WPM) you have sent 250 time-units
 * (using correct spacing).
 *
 * 250 time-units into 60 seconds per minute = 240 milliseconds per time-unit.
 */

const unsigned long     WORDS_PER_MINUTE    = 20;
const unsigned long     UNITS_PER_WORD      = 50;

const unsigned long     tmsSECOND           = 1000UL;
const unsigned long     tmsMINUTE           = 60 * tmsSECOND;
const unsigned long     tmsWPM_SCALER       = tmsMINUTE / (WORDS_PER_MINUTE * UNITS_PER_WORD);

void signal_spacing(unsigned long length)
{
    for ( ; length--; )
    {
        std::cout << " ";
    }
}

void signal_element(char const signal)
{
    std::cout << signal;
    std::cout.flush();
}

void signal(morse_encoding_t const encoding)
{
    for ( size_t mask = (1 << encoding.count); mask >>= 1; )
    {
        signal_element((encoding.elements & mask) ? '-' : '.');
        if ( 1 != mask )
        {
            signal_spacing(INTRA_CHAR_GAP);
        }
    }
}

void morse(const char* psz)
{
    if ( *psz )
    {
        do
        {
            const morse_encoding_t encoding = char2encoding(*psz++);
            if ( ! encoding.count )
            {
                continue;
            }
            
            signal(encoding);
            signal_spacing((' ' == *psz) ? WORD_GAP : CHAR_GAP);
            
        } while ( *psz );
    }
}

void morse(char const ch)
{
    const morse_encoding_t encoding = char2encoding(ch);
    if ( encoding.count )
    {
        signal(encoding);
    }
}

void loop()
{   }

void setup()
{
    morse("THE QUICK BROWN FOX JUMPED OVER THE LAZY DOGS BACK");
}

void init()
{   }

int main(int const argc, const char* const argv[])
{
    init();
    
    setup();
    
    for ( ; ; )
    {
        loop();
    }
    
    return 0;
}

Gaddsy:
Basically the input and output both have to be on the serial port.

I have made an example sketch to do that.
Switching from encoding to decoding is automatic.
No sending of morse code signals included, just encoding/decoding between ASCII and dots/dashes using Serial.

Enter letters and digits ==> encoding
Enter dots and dashes ==> decoding

/* Serial Morse Encoder and Decoder
 *  written by 'jurs' for Arduino forum
 *  Usage: 
 *  Use the serial monitor to send ASCII text ==> will be encoded to morse code
 *  Use the serial monitor to send dots and dashes ==> will be decoded to ASCII
 */

char morseCode[]={ // first bit set tells where morse encoding starts
  B00000101, // A = .-
  B00011000, // B = -...
  B00011010, // C = -.-.
  B00001100, // D = -..
  B00000010, // E = .
  B00010010, // F = ..-.
  B00001110, // G = --.
  B00010000, // H = ....
  B00000100, // I = ..
  B00010111, // J = .---
  B00001101, // K = -.-
  B00010100, // L = .-..
  B00000111, // M = --
  B00000110, // N = -.
  B00001111, // O = ---
  B00010110, // P = .--.
  B00011101, // Q = --.-
  B00001010, // R = .-.
  B00001000, // S = ...
  B00000011, // T = -
  B00001001, // U = ..-
  B00010001, // V = ...-
  B00001011, // W = .--
  B00011001, // X = -..-
  B00011011, // Y = -.--
  B00011100, // Z = --..
  B00111111, // 0 = -----
  B00101111, // 1 = .----
  B00100111, // 2 = ..---
  B00100011, // 3 = ...--
  B00100001, // 4 = ....-
  B00100000, // 5 = .....
  B00110000, // 6 = -....
  B00111000, // 7 = --...
  B00111100, // 8 = ---..
  B00111110, // 9 = ----.
};

#define NUMCHARS sizeof(morseCode)

char morseChars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

void sendMorseChar(char c)
{
  // invalid ASCII chars will not be encoded into anything
  // valid ASCII chars are encoded into morse dots/dashes
  // then finish with sending a space character ' '
  char* found= strchr(morseChars, c);
  if (found==NULL) return;
  else
  {
    byte morse= morseCode[found-morseChars];
    boolean firstBitFound=false;
    for (int i=7; i>= 0; i--) 
    {
      byte thisBit= bitRead(morse,i);
      if (firstBitFound)
      {
        if (thisBit) Serial.print('-');
        else Serial.print('.');
      }
      else if (thisBit) firstBitFound=true;
    }
  }
  Serial.print(" ");
}

char handleMorseInput(char c)
{ // char c==0 is for clearing internal receiveBuf
  // char c==1 is for evaluating internal receiveBuf
  static byte receiveBuf;
  if (c==0) 
  { 
    receiveBuf=1; // set 0-bit
    return 0;
  }
  else if (c==1)
  {
    for (int i=0;i<NUMCHARS;i++)
    {
      if (receiveBuf==morseCode[i])
      {
        return morseChars[i];
      }
    }
    return('*'); 
  }
  else if (c=='.') receiveBuf= receiveBuf<<1;
  else if (c=='-') receiveBuf= (receiveBuf<<1) | 1;
  return 0;
}

void handleSerialInput()
{
  static boolean isMorseInput=false;
  if (!Serial.available()) return;
  char c=Serial.read();
  // automatic detection of morse or ASCII input
  if (c=='.' || c=='-') 
  {
    if (!isMorseInput)
    { // switch to morse input and clear input buffer
      isMorseInput= true;
      handleMorseInput(0);
    }
    handleMorseInput(c);
  }
  else
  {
    if (isMorseInput)
    {
      c= handleMorseInput(1); // retrieve decoded char from input buffer
      Serial.print(c);
      isMorseInput=false;
    }
    else if (c==' ') Serial.print(' ');
    else if (c=='\n') Serial.println();
    else if (c>32) // filter out control characters and international special characters
    {
      sendMorseChar(toupper(c));
    }
  }
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  handleSerialInput();
}

@jurs: pretty neat! I made a slight mod to your code to avoid looping through all characters. Most of my code change appears in the docode() function. (I haven't tested it thoroughly yet.)

/* Serial Morse Encoder and Decoder
 *  written by 'jurs' for Arduino forum
 *     Modified by econjack 12/4/2015 to avoid looping through all codes
 *  Usage: 
 *  Use the serial monitor to send ASCII text ==> will be encoded to morse code
 *  Use the serial monitor to send dots and dashes ==> will be decoded to ASCII
 */

char morseCode[]={ // first bit set tells where morse encoding starts
  B00000101, // A = .-
  B00011000, // B = -...
  B00011010, // C = -.-.
  B00001100, // D = -..
  B00000010, // E = .
  B00010010, // F = ..-.
  B00001110, // G = --.
  B00010000, // H = ....
  B00000100, // I = ..
  B00010111, // J = .---
  B00001101, // K = -.-
  B00010100, // L = .-..
  B00000111, // M = --
  B00000110, // N = -.
  B00001111, // O = ---
  B00010110, // P = .--.
  B00011101, // Q = --.-
  B00001010, // R = .-.
  B00001000, // S = ...
  B00000011, // T = -
  B00001001, // U = ..-
  B00010001, // V = ...-
  B00001011, // W = .--
  B00011001, // X = -..-
  B00011011, // Y = -.--
  B00011100, // Z = --..
  B00111111, // 0 = -----
  B00101111, // 1 = .----
  B00100111, // 2 = ..---
  B00100011, // 3 = ...--
  B00100001, // 4 = ....-
  B00100000, // 5 = .....
  B00110000, // 6 = -....
  B00111000, // 7 = --...
  B00111100, // 8 = ---..
  B00111110, // 9 = ----.
};

#define NUMCHARS sizeof(morseCode)

char morseChars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

void sendMorseChar(char c)
{
  // invalid ASCII chars will not be encoded into anything
  // valid ASCII chars are encoded into morse dots/dashes
  // then finish with sending a space character ' '
  char* found= strchr(morseChars, c);
  if (found==NULL) return;
  else
  {
    byte morse= morseCode[found-morseChars];
    boolean firstBitFound=false;
    for (int i=7; i>= 0; i--) 
    {
      byte thisBit= bitRead(morse,i);
      if (firstBitFound)
      {
        if (thisBit) Serial.print('-');
        else Serial.print('.');
      }
      else if (thisBit) firstBitFound=true;
    }
  }
  Serial.print(" ");
}

char handleMorseInput(char c)
{ // char c==0 is for clearing internal receiveBuf
  // char c==1 is for evaluating internal receiveBuf
  static byte receiveBuf;
  if (c==0) 
  { 
    receiveBuf=1; // set 0-bit
    return 0;
  }
  else if (c==1)
  {
    for (int i=0;i<NUMCHARS;i++)
    {
      if (receiveBuf==morseCode[i])
      {
        return morseChars[i];
      }
    }
    return('*'); 
  }
  else if (c=='.') receiveBuf= receiveBuf<<1;
  else if (c=='-') receiveBuf= (receiveBuf<<1) | 1;
  return 0;
}

void handleSerialInput()
{
  static boolean isMorseInput=false;
  static char buff[7];
  static byte charsRead = 0;

  if (!Serial.available()) return;
  char c = toupper(Serial.read());
  // automatic detection of morse or ASCII input - . ... -
  switch (c) {
    case '.':
      buff[charsRead++] = c;
      break;
    case '-':
      buff[charsRead++] = c;
      break;
    case ' ':       // Delimits characters
    case '\n':      // input end
      buff[charsRead] = '\0';
      docode(buff);
      charsRead =  0;
      break;
    default:
      if (c > 32) // filter out control characters and international special characters
      {
        sendMorseChar(toupper(c));
      }
      break;
  }
}

void docode(char *code) {
  static char alphaSet[] = "##TEMNAIOGKDWRUS##QZYCXBJP#L#FVH09#8###7#####/-61#######2###3#45";
  int i;
  byte index = 32;
  int sum;
  int len = strlen(code);
  
  sum = 1 << len;     // Sentinel bit set

  len--;                                         // Bits remaining to inspect
  for (i = 0; i <= len; i++) {                   // Loop through those bits
      if (code[i] == '.') {                        // If a dit, treat a binary value, base 2
       sum += 1 << (len - i);
      }
  }
  if (sum > sizeof(alphaSet)) {                    // If outside of Alpha array, must be punctuation
    printPunctuation(sum);  // The value we parsed is bigger than our character array
  } else {
    Serial.print(alphaSet[sum]);
  }
}

/*****
  Punctuation marks are made up of more dits and dahs than letters and numbers.
  Rather than extend the character array out to reach these higher numbers we
  will simply check for them here. This funtion only gets called when sum is
  greater than the sizeof the alphaSet[] array.

  Parameter List:
    int val        the value of the index after bit shifting

  Return value:
    void
*****/
void printPunctuation(int val) {

  char c;
  
  switch (val) {
    case 71:
      c = ':';
      break;
    case 76:
      c = ',';
      break;
    case 84:
      c = '!';
      break;
    case 94:
      c = '-';
      break;
    case 97:
      c = 39;    // Apostrophe
      break;
    case 101:
      c = '@';
      break;
    case 106:
      c = '.';
      break;
    case 115:
      c = '?';
      break;
    case 246:
      c = '

;
      break;
    case 122:
      c = 's';
      Serial.println(c);
      c = 'k';
      break;
    default:
      c = '#';    // Should not get here
      break;
  }
  Serial.println(c);
}
void setup() {
  Serial.begin(9600);
}

void loop() {
  handleSerialInput();
}