We now have a way that our program can react to the events. What we need next is a way that we can store the dots and dashes and use the stored information to identify a particular code.
We could think of dot as meaning 1 and dash as meaning 0. This means that I could represent a morse code character in a single byte, as long as it doesn't contain more than 8 items. For example, the letter A is dot dash.
A = binary 10 - which is decimal 2
The snag with just using bits in this way is that I also need to know where the dots and dashes end, for example I would not be able to tell A (dot dash) from Q (dash dash dot dash):
A = binary 10 - which is decimal 2
Q = binary 0010 - which is decimal 2
I can get around this by storing the length of each item as well as a bit pattern. This means that in the case of A count two events and have the pattern value 2, but for Q I count four events and have the pattern value 2. When I want to decide what a particular character is I simply look for the matching pattern and length pair.
On the right you can see my look up tables. I have arranged them so that they are easy to makes sense of. The idea is that when we find the matching pattern pairs, its offset in the array will identify the character, for example the pattern for F is at location 5 in the array, as is the characteristic length. This is another example of an array used as a look up table.
The function decode_character
will look through the arrays until it finds both matching length and pattern. At this point the for loop
is stopped. We can then use the value of i
which the loop stopped at to identify the character which this pattern represents. Note that if no character is recognized the for loop
will hit the limit and end with i
holding the limit value. I look for this specially and return the character '*
' if no match is found.
/* Ex 9.2 Morse Decoder */
const unsigned char patterns [26] =
{
/* A B C D E F G */
2, 7, 5, 3, 1, 13, 1,
/* H I J K L M N */
15, 3, 8, 2, 11, 0, 1,
/* O P Q R S T U */
0, 9, 2, 5, 7, 0, 6,
/* V W X Y Z */
14, 4, 6, 4, 3
} ;
const unsigned char lengths [26] =
{
/* A B C D E F G */
2, 4, 4, 3, 1, 4, 3,
/* H I J K L M N */
4, 2, 3, 3, 4, 2, 2,
/* O P Q R S T U */
3, 4, 4, 3, 3, 1, 3,
/* V W X Y Z */
4, 3, 4, 4, 4
} ;
/* given the length and pattern */
/* of a character this function */
/* will return the matching */
/* character - or '*' if it is */
/* not recognized */
unsigned char decode_character (
unsigned char pattern,
unsigned char length )
{
unsigned char i ;
/* search the arrays for a */
/* matching pair of length */
/* and pattern */
for ( i=0 ; i < 26 ; i = i + 1 )
{
if ((pattern==patterns[i]) &&
(length==lengths[i]) )
{
/* stop the loop if */
/* a match is found */
break ;
}
}
if ( i == 26 )
{
/* if i reached 26 this */
/* means that no match */
/* was found */
return '*' ;
}
else
{
/* add i onto the code */
/* of A to get the */
/* character */
return 'A' + i ;
}
}