Close

Encoding the Morse Code Stream

A project log for Morse Code Decoder

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

agpcooperagp.cooper 12/12/2022 at 06:470 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 ...


Discussions