Close
0%
0%

Morse Code Decoder

There are a number of Morse Code decoders out there for the Arduino. This is my take.

Similar projects worth following
Morse Code Decoder
===================
There is a really cool "Instructables" called "Morse Code Iambic Trainer and Decoder" by "SCD" or Scot L. Baker (https://www.instructables.com/Morse-Code-Iambic-Trainer-and-Decoder/).

He uses Goertzel algorithm to detect the Morse Code tone, some digital filtering, words per minute (WPM) time period tracking, and some other cool techniques.

So here is my take for the Morse Code to ASCII code section (using a completely different method).

TBC ...

  • Encoding the Morse Code Stream

    agp.cooper12/12/2022 at 06:47 0 comments

    Encoding the Morse Code Stream

    This sub-section takes a morse code stream that is HIGH for mark (key pressed) and LOW for Space (key released). It is assumed to be debounced.

    One approach to encode the stream is to use a tree structure like this:

    (source: https ://i.pinimg.com/736x/5d/61/47/5d6147361620f3a5608b8502eedf6d8f.jpg)

    To use this approach we would need a clock to determine Dits from Dahs, code spaces, from character spaces, and word spaces.

    We could code a "dot" as a 0 and a "dash" as a 1, as bits in an integer (or byte), to index an array.

    The problem is that E would be encoded as 0, I as 00 and S as 000, etc.

    It would not be possible to decode the tree as 0, 00 and 000, etc., are all zero.

    We need to include a "guard" bit. In this case the tree would look like this:

    We need a space code (1) anyway, and the error code (0) is arbitrary.

    The tree would be coded as an array:

    // Morse Code Lookup Array:
    char MorseEnCode[64]={
      '~',' ','E','T','I','A','N','M','S','U','R','W','D','K','G','O',
      'H','V','F','_','L','_','P','J','B','X','C','Y','Z','Q','_','_',
      '5','4','_','3','_','_','_','2','&','_','+','_','_','_','_','1',
      '6','=','/','_','_','_','(','_','7','_','_','_','8','_','9','0'
    };

    Here illegal morse code indexes have the "_" character rather than "?" character.

    We could construct a 128 node array as well:

    char MorseCode[128]={
      '~',' ','E','T','I','A','N','M','S','U','R','W','D','K','G','O',
      'H','V','F','_','L','_','P','J','B','X','C','Y','Z','Q','_','_', 
      '5','4','_','3','_','_','_','2','&','_','+','_','_','_','_','1',
      '6','=','/','_','_','_','(','_','7','_','_','_','8','_','9','0', 
      '_','_','_','_','_','_','_','_','_','_','_','_','?','_','_','_',
      '_','_','"','_','_','.','_','_','_','_','@','_','_','_',"'",'_',
      '_','-','_','_','_','_','_','_','_','_','_','!','_',')','_','_',
      '_','_','_',',','_','_','_','_',':','_','_','_','_','_','_','_'
    };

    To encode the morse code stream, the following code fragment could be used:

              // Reset Code
              Code=1;
              ...
              if (Dit) {
                Code=(Code<<1);
              } else if (Dah) {
                Code=(Code<<1)+1;
              } else {
                ...
              }
              ...
              // Convert (Morse) Code to ASCII character
              symbol=morseCode[Code];
    


    Converting the (Morse) Code back to morse code

    Basically the morse code is stored in an integer/byte in reverse order.

    So to decode morse code we need to reverse the out the bits until the guard bit is found., then "export" the bits as dits and dahs (in reverse order).

    Here is some recursive code that could be used:

    void deCode1(byte code)
    {
      if (code>3) deCode1(code>>1);
      if ((code&1)==0) {
        // Serial.print(".");
        setDit(MorseOut);
      } if ((code&1)==1) {
        // Serial.print("-");
        setDah(MorseOut);
      }
      return;
    }
    
    void deCode(byte code)
    {
      if (code==0) {
        // Serial.print("........ ");            // Error
        for (int i=0;i<8;i++) setDit(MorseOut);
        setEndChar(MorseOut);
      } else if (code==1) {
        // Serial.print(" ");                    // Space
        setSpace(MorseOut);
      } else { 
        deCode1(code);                           // Char Space
        // Serial.print("");
        setEndChar(MorseOut);
      }
      return;
    }

    The above code would use an array like this to look up the morse (code):

    byte MorseDeCode[64]={
       1, 0, 0, 0, 0, 0,40, 0,54, 0, 0,42, 0, 0, 0,50,
      63,47,39,35,33,32,48,56,60,62, 0, 0, 0,49, 0, 0,
       0, 5,24,26,12, 2,18,14,16, 4,23,13,20, 7, 6,15,
      22,29,10, 8, 3, 9,17,11,25,27,28, 0, 0, 0, 0,19
    };

    Interrupt Service Routine

    I have used the ISR(TIMER0_COMPB_vect)  interrupt serve vector to poll the morse code encoder routine. Although this timer is used by the milli-second clock, Comparator B is unused. Using this comparator will poll the encoder 0.977 ms. 

    TBC ...


View project log

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates