CHAPTER 6. DETAILED SYSTEM DESIGN 20
output forms the input of the subsequent filter. Creating instances of all filter classes
inside a module, and building the filter chain, is handled by the framework. How-
ever, it needs a hint to determine the sequence in which filters are to be arranged.
In general, this hint consists of a single statement placed inside your filter’s .cpp file:
RegisterFilter( MyFilter, 2.C );
The first argument to this statement is your filter’s class name; the second argument
is a string value (given without quotes) that determines the relative position of your
filter in the filter chain. This is done applying the simple rule that the filter positions
in the chain match the alphanumeric sorting order of the filters’ associated position
strings. This scheme allows you to place an additional filter between existing ones
without changing the position strings of the existing filters.
In principle, this allows to add filters to a module’s filter chain without modifi-
cation to existing source code, simply by adding a .cpp file with a RegisterFilter
statement to the project.
However for Signal Processing modules, it appears more desirable to have an
explicit representation of the entire filter chain centralized in one file. So there is,
for each individual Signal Processing module, one file UFilterHandling.cpp that
defines the filter chain as a sequence of Filter statements (see Section 6.6.8 for an
example).
6.6.6 Presenting data to the operator user
Your filter may have information that it wants to present to the user – e.g., the EEG
signal might appear graphically in a window, or an application task log should be
presented. Packaging this information into core messages, and sending these to the
operator module, is handled by the GenericVisualization class.
Typically, to visualize data this way, you will add a data member of type
GenericVisualization to your filter class – see Section 6.6.8 for an example.
6.6.7 Tutorial: Implementing Your Own Data Acquisition
Data acquisition modules are factored into code required for any hardware, and code
required to access a specific hardware. What you need to do is provide a function
that waits for and reads A/D data (line 3 in the EEG source pseudo code of section
6.3), together with some helper functions that perform initialization and cleanup
tasks. Together these functions form a class derived from GenericADC.
In this tutorial, we consider this scenario: Your Tachyon Corporation A/D card
comes with a C-style software interface declared in a header file "TachyonLib.h"
that consists of three functions