Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
10/08/06 14:11
Modified:
  10/08/06 14:30

Read: times


 
Msg Score: +1
 +1 Good Answer/Helpful
#126011 - Morse Code Decoding Hints
Responding to: ???'s previous message
 
Hello Arif,

I did this a long time ago.  Here are the basic steps:

1.  Make a table in RAM that keeps track of the duration of each
    ON time and each OFF time.  The ON times will correspond to
    the dots and the dashes, and the OFF times will correspond to
    the silent periods between the dots and the dashes.

    ON or OFF   Time
    ----------------

       ON       51
       OFF      47
       ON       142
       OFF      151
       ON       50
       OFF      48
       ON       162
       OFF      51
       ON       48
       OFF      143
       ON       51
       OFF      45
       ON       49
       OFF      153
       ON       45
       OFF      52
       ON       46
       OFF      51
       ON       151
       OFF      55
       ON       59
       OFF      160

    The entries in the table will always alternate ON OFF ON OFF
    ON OFF ...

    A dash is supposed to be three times as long as a dot.  The
    space between dots and dashes is supposed to be the same as a
    dot.  The space between letters is supposed to be the same as
    a dash.  So in the example above, the dot time is about 50,
    and the dash time is about 150.

    The table should be long enough to hold several seconds worth
    of information.  At each transition of the input signal, throw
    away the oldest entry in the table and add a new one.  That
    way, the table always contains the ON and OFF times for the
    most recent few seconds of input.

2.  Every time you make a new addition to the table, examine the
    table to determine the average dot time and the average dash
    time.  Once you know these numbers, you can set a threshold
    halfway between them.  Any ON time smaller than the threshold
    is a dot, and any ON time longer than the threshold is a dash.

    If the speed of the incoming data changes slowly, the
    threshold will also change slowly and everything will work
    fine.  However, if the speed of the incoming data changes
    quickly, then the decoder will lose synchronization until the
    table fills up with entries at the new speed.  At that point
    it will start to work again.

3.  Every time you see an OFF time that is longer than the
    threshold, you know you have found a space beteween two
    letters.  At that point, you can look at the ON times in the
    table following the previous letter to decode the letter than
    you just received.  If the OFF time is much longer than
    the treshold, then you have found a space between words and
    you should output a blank character as well.

That's the basic idea.  Now, Step #2 is the tricky one.  If you
can do Step #2, then the rest is easy.  How do you determine the
average dot time and the average dash time?  Here is one idea:

1.  Copy the times from the table to a separate list and sort them
    in order from smallest to largest.

2.  Starting at the beginning, scan through the sorted list and
    look for the magic spot where the next value is greater than
    twice the average of all the previous values.

3.  The average of all the times before the magic spot is the
    average dot time.  The average of all the times after the
    magic spot is the average dash time.

As near as I can remember, that's the method I used when I did
this a long time ago.

The code that follows shows another approach.  I developed it to
divide blood cell images into two groups (big ones and little
ones) by area, but it should work equally well to divide Morse
code signals into two groups (dots and dashes) by time.

-- Russ

/* ////////////////////////////////////////////////////////////////////////////
                                  tfinder.cpp
///////////////////////////////////////////////////////////////////////////////
DESCRIPTION:    This module contains Russ's threshold finder.

REVISIONS:       8 Feb 01 - RAC - Genesis
//////////////////////////////////////////////////////////////////////////// */

#include "stdafx.h"
#include "tfinder.h"

/* ////////////////////////////////////////////////////////////////////////////
                                FindThreshold()
///////////////////////////////////////////////////////////////////////////////
DESCRIPTION:    This function automatically calculates a threshold value for
                discriminating two populations that are assumed to lie within a
                set of data.  For example, if the given batch of data contains
                leukocyte areas, this function will find the area threshold
                for discriminating lymphocytes (which are small) from other
                (larger) cells.

METHOD:         Here's how this function works, explained in terms of the cell
                area example:

                A.  Pick an arbitrary threshold T somewhere between the
                    smallest and biggest cells observed.

                B.  Place the cells with areas greater than T in population B
                    and those with areas less than or equal to T in population
                    S.

                C.  Calculate the mean size of the cells in population B.

                D.  Repeat for population S.

                E.  Calculate the sum of the absolute values of the differences
                    between the sizes of the cells in population B and
                    population B's mean cell size.  Call this number Deviation
                    B.

                F.  Repeat for population S.  Call the result Deviation S.

                G.  Calculate a Total Deviation = Deviation B + Deviation S.

                H.  Repeat steps A through G for all possible threshold values.

                I.  Choose the threshold value which produces the smallest
                    Total Deviation as the one that best separates the two
                    populations.

NOTE:           Pay particular attention to the "greater than" and "less than
                or equal to" provisions of Step B.

REVISIONS:       8 Feb 01 - RAC - Genesis, with hints from some Excel spread-
                                  sheets used to develop the idea.
//////////////////////////////////////////////////////////////////////////// */

int FindThreshold(int *pData, int count) {

    int         minValue;                       /* Minimum data value */
    int         maxValue;                       /* Maximum data value */
    int         i;                              /* A generic integer */
    int         currentThreshold;
    int         minThreshold;
    int         currentTotalDeviation;
    int         minTotalDeviation;
    int         bigMean;                        /* Mean of big population */
    int         smallMean;                      /* Mean of small population */
    int         bigCount;                       /* Size of big population */
    int         smallCount;                     /* Size of small population */

/*  Make an initial pass through the data to find the minimum and maximum
    values.  */

    maxValue = INT_MIN;                         /* Set min and max to */
    minValue = INT_MAX;                         /*  incredible values */
    for (i=0; i<count; i++) {                   /* For each data item */
        if (pData[i] < minValue) {              /* Remember it if it's the */
            minValue = pData[i];                /*  new minimum value */
            }
        if (pData[i] > maxValue) {              /* Remember it if it's the */
             maxValue = pData[i];               /*  new maximum value */
            }
        }                                       /* End 'for each data item' */

/*  For each possible threshold value, calculate the Total Deviation.  At the
    same time, be sure to keep track of which threshold value resulted in the
    smallest Total Deviation.  */

    minTotalDeviation = INT_MAX;                /* Inz to incredible value */
    for (currentThreshold = minValue;           /* For all possible */
         currentThreshold < maxValue;           /*  threshold values */
         currentThreshold++) {

    /*  Rattle through the data to find the sizes and means of the two
        populations.  */

        bigMean = smallMean = 0;                /* No items summed yet */
        bigCount = smallCount = 0;              /* No items counted yet */
        for (i=0; i<count; i++) {               /* For each data item */
            if (pData[i] > currentThreshold) {  /* Place in the appropriate */
                bigMean += pData[i];            /*  population, depending on */
                bigCount++;                     /*  whether or not it is */
                }                               /*  above the threshold */
            else {
                smallMean += pData[i];
                smallCount++;
                }
            }                                   /* End 'for each data item' */
        bigMean = (bigMean + (bigCount / 2)) /  /* Calculate the actual mean */
            bigCount;                           /*  values here */
        smallMean = (smallMean + (smallCount /
            2)) / smallCount;

    /*  Now pass through the data once more to find the Total Deviation for the
        current threshold.  */

        currentTotalDeviation = 0;              /* No deviations yet */
        for (i=0; i<count; i++) {               /* For each data item */
            if (pData[i] > currentThreshold) {  /* Sum the difference twixt */
                currentTotalDeviation +=        /*  the data value and the */
                    abs(pData[i] - bigMean);    /*  mean of its population. */
                }
            else {
                currentTotalDeviation +=
                    abs(pData[i] - smallMean);
                }
            }                                   /* End 'for each data item' */

        if (currentTotalDeviation <             /* Track the smallest Total */
            minTotalDeviation) {                /*  Deviation observed along */
            minTotalDeviation =                 /*  with the threshold value */
                currentTotalDeviation;          /*  that produced it.  */
            minThreshold = currentThreshold;
            }
        }                                       /* End 'for all thresholds' */
    return minThreshold;                        /* The answer */
    }                                           /* End FindThreshold() */
 



List of 9 messages in thread
TopicAuthorDate
Morse Code Decoding Algorithm            01/01/70 00:00      
   ooh thats a hard one            01/01/70 00:00      
      having said that            01/01/70 00:00      
   Autobaud it to death            01/01/70 00:00      
   Morse Code Decoding Hints            01/01/70 00:00      
      Thanks            01/01/70 00:00      
         You're Welcome            01/01/70 00:00      
   QRZ QRZ QRZ            01/01/70 00:00      
   We had a product...            01/01/70 00:00      

Back to Subject List