Streaming and Context

Top  Previous  Next

It is important to realize that data is streamed to your plug-in and it is expected to stream back its data.  Your plug-in will not have random access to the data or even know how much data it will receive.  Since your plug-in is sharing the system with a couple dozen other plug-ins, you do not want to absorb the data into an internal array, process it and then send back your results.  This is very inefficient in resource usage and is slow.  The plug-in must process a single piece of data at a time and immediately return.  This requires a certain mindset during development.
 
The plug-in must maintain its state in the protocol while parsing so that it can interpret each piece of data in context.  The example 'RAWSTATE.CPP' uses static variables to remember the current state of the clock and enable lines.  These are used for edge detection.  In each parse() call, it examines these variables to see the previous state of the lines and compares them to the current state to detect transitions.  Before exiting, it updates the clk_was and en_was variables to provide context for the next call.  This is a typical way of maintaining simple context information.
 
This works in simple parsers, but in more complex parsers (like protocol parsers), you probably need to save more than line level context; you will need to save your protocol context (like 'I'm waiting for the sub-command to command 5').  For example, it might receive the first byte of a frame and interpret it as a command.  It can probably send back a field at this point to print the command, but it must remember which command was received so that when the next byte is received, it will know what to do with it.  No doubt its meaning varies with which command was sent. 
 
State machines are very well suited to this task.  A single state variable maintains your current protocol context.  Additional static variables are used to remember significant information (like the edge detection mentioned above.)  For example, you might be in state 'waiting for address low in command all-call'.  In this case, you probably stored address-high in a previous state.  When both are gathered, you might send out a single field with the combined value and then move on to state 'waiting for checksum'.  You update your state variable before returning from each event.  At the start of each event, you look at the state variable for context in evaluating the current data.
 
We are not going to discuss state machine design, but there is a lot of information on the web (search for 'finite state machine design'.)  We use a simple state machine in the 'RawDAC8045' example.