We now have enough working code to plug in the storage and decode and run our program with the test data. Since I am fairly happy with the state behaviour I can dispense with the debug setting and see if the program prints out the message which my patterns represent. The next version of my program is [Exercise 9.2]. When it runs it decodes the characters in the test array and prints them out. Note that I have modified the behaviour of the state machine so that it actually performs the actions rather than just having comments in the appropriate places.
If you load up the program and run it you will find that it prints out the characters which the patterns represent. You can change the test data so that it prints your name if you wish. In real life I would create a test data set which contains every possible character in the alphabet.
/* EX 9.2 Morse Characters */
/* Rob Miles 2000 */
#include <lcdlib.h>
#include <utils.h>
/* values for the events */
#define DOT_EVENT '.'
#define DASH_EVENT '-'
#define SPACE_EVENT 32
#define STUCK_EVENT '*'
/* values for the states */
#define BUSY_STATE 'B'
#define QUIET_STATE 'Q'
/* #define DEBUG */
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 ;
}
}
/* global variables used to hold */
/* the length and bit pattern of */
/* the character being loaded */
unsigned char pattern = 0 ;
unsigned char length = 0 ;
/* start is called to reset the */
/* pattern and length items */
void start ( void )
{
pattern = 0 ;
length = 0 ;
}
/* store dot stores a dot - the */
/* existing pattern is shifted */
/* left and a dot bit is added */
/* then the length is increased */
void store_dot ( void )
{
pattern = pattern << 1 ;
pattern = pattern | 1 ;
length = length + 1 ;
}
/* store dash doesn't add a bit */
/* but does everything else that */
/* store dot does */
void store_dash ( void )
{
pattern = pattern << 1 ;
length = length + 1 ;
}
/* state variable - set at QUIET */
unsigned char morse_state =
QUIET_STATE ;
/* we call the function to deal */
/* with an event. How it behaves */
/* depends on the current state */
void do_morse (unsigned char event)
{
#ifdef DEBUG
lcd_print_ch ( event ) ;
lcd_print_ch ( morse_state ) ;
#endif
/* use a switch to select the */
/* code for the current state */
switch ( morse_state )
{
case BUSY_STATE :
/* now have a switch for each */
/* event which might happen */
/* in this busy state */
switch ( event )
{
case DOT_EVENT :
/* store the dot here */
break ;
case DASH_EVENT :
/* store the dash here */
break ;
case SPACE_EVENT :
/* work out the code */
/* and move to QUIET */
/* state */
morse_state = QUIET_STATE ;
break ;
case STUCK_EVENT :
/* go to quiet state */
morse_state = QUIET_STATE ;
}
/* now handle events in */
/* quiet state */
case QUIET_STATE :
switch ( event )
{
case DOT_EVENT :
/* store the dot here */
/* move to BUSY state */
morse_state = BUSY_STATE ;
break ;
case DASH_EVENT :
/* store the dash here */
/* move to BUSY state */
morse_state = BUSY_STATE ;
break ;
case SPACE_EVENT :
/* do nothing */
break ;
case STUCK_EVENT :
/* do nothing */
break ;
}
}
#ifdef DEBUG
lcd_print_ch ( morse_state ) ;
#endif
}
/* here is a test sequence for */
/* the morse code reader. I am */
/* sending three characters */
unsigned char test_sequence [] =
{
/* P */
DOT_EVENT, DASH_EVENT, DASH_EVENT,
DOT_EVENT, SPACE_EVENT,
/* I */
DOT_EVENT, DOT_EVENT, SPACE_EVENT,
/* C */
DASH_EVENT, DOT_EVENT, DASH_EVENT,
DOT_EVENT, SPACE_EVENT,
/* end marker */
0x00
} ;
void main ( void )
{
unsigned char i ;
lcd_start () ;
for ( i=0 ;
test_sequence [i] != 0 ;
i = i + 1 )
{
do_morse ( test_sequence [i] ) ;
}
while (1) ;
}