Saturday, June 2, 2012

Morse Code Encoder/Decoder
A Programming Adventure
Samuel Morse

Introduction

Every once in a while I think of interesting and odd programming tasks/projects.  I wake up in the morning and some random idea comes to mind.  I write it down, throw some requirements on paper and write a few sentences on how I plan to write it.  After some well writen words I begin.

Samuel Morse

 This time around I decided to read up on Samuel Morse; after all, computing in general shares allot with Morse code.  I consider Samuel Morse to be one of the earliest computer language architects; he unknowingly created a basic language of communication with two symbols dot (.) and dash (-) (a synonym with binary 1s and 0s).  The symbols in sequence and in specific order can create a wide range of codes that are mapped to individual alphabetic characters; I think of them as another translation mechanism such as ASCII.  There is a great book by Charles Petzold that describes Morse code in very cool detail:

Code by Charles Petzold

The Morse code system is quite impressive.

Morse Code Encoder/Decoder Implementation

My objective was to write an Morse code encoder and decoder.  Since the translation table is available on the net, I took the tables and created some functions that would be capable of reading a character or code and output its relevant value.  This way, any string could be encoded or decoded quickly.

I knew that the Morse code would probably be dependent on the character.  I first created a translation table based on a switch block that would check for an ASCII code and then output the relevant Morse code.  This was bad;  when I needed to decode back to an alphabetic character, it caused some issues: I was unable to decode easily because the ASCII code was not in a particularly easy order (A=65, etc).

I decided to write two tables:

char alpha_codes[] = {
 '*',
 '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', '.',
 ',', '?', '\\', '!',
 '/', '(', ')', '&',
 ':', ';', '=', '+',
 '-', '_', '"', '$',
 '@', ' '
};



char *morse_codes[] = {
 "undef",
 ".-", "-...", "-.-.", "-..",
 ".", "..-.", "--.", "....",
 "..", ".---", "-.-", ".-..",
 "--", "-.", "---", ".--.",
 "--.-", ".-.", "...", "-",
 "..-", "...-", ".--", "-..-",
 "-.--", "--..", "-----", "..---",
 "...--", "....-", ".....", "-....",
 "--...", "---..", "----.", ".-.-.-",
 "--..--", "..--..", ".----.", "-.-.--",
 "-..-.", "-.--.", "-.--.-", ".-...",
 "---...", "-.-.-.", "-...-", ".-.-.",
 "-....-", "..--.-", ".-..-.", "...-..-",
 ".--.-.", " "
};


Then four functions:

char *GetMorseCode(int index){
 return morse_codes[index];
}



char GetAlphaCode(int index){
 return alpha_codes[index];
}



int GetAlphaCodeIndex(const char c){
 unsigned int ret = 0;
 unsigned count = (sizeof(alpha_codes) / sizeof(alpha_codes[0]));
 for(int i = 0; i < count; i++){
  if(c == GetAlphaCode(i)){
   ret = i;
   break;
  }
 }
 return ret;
}





int GetMorseCodeIndex(const char *morse){
 unsigned int ret = 0;
 unsigned int count = (sizeof(morse_codes) / sizeof(morse_codes[0]));
 for(int i = 0; i < count; i++){
  if(strcmp(GetMorseCode(i), morse) == 0){
   ret = i;
   break;
  }
 }
 return ret;
}


The first function simply returns a string of Morse code based on an index.  This allows a Morse code to be called easily from index 0 to it's max; the same is performed for alphabetic characters.  The third/forth functions take a character/morse code as their argument which in turn returns the index of the character/morse code within the array.  The comparison of the character is made with a strcmp() function instead of the ASCII code.  This is far more flexible than the switch() translation table.  With these tables in place, it simplified both encoding and decoding since all I needed was to know each table's index value.

Translating from an alpha character to Morse is:

GetMorseCode(GetAlphaCodeIndex('A'));

And from Morse code to Alpha:

GetAlphaCode(GetMorseCodeIndex(".-"));

Conclusion

These functions can then be used to create more elaborate processing on strings of alpha or morse codes.

No comments:

Post a Comment