// This header file is used only by the Cocoon documentation utility.
/* ------------------------------------------------------------------
LIBRARY
IbcAppFramework

OVERVIEW
IbcAppFramework is an <a href="../conceptReview/appFramework.html">
application framework</a> for IBC applications. An IBC 
application runs under the VxWorks RTOS, communicates wih
an IBC-196 CPU via serial line, and uses DataManager 
to receive user commands and distribute telemetry.

The framework is implemented as several C++ objects which are 
accessed by three coordinated VxWorks tasks:

  Main task: Spawns Sampler and Command Monitor tasks, initializes
  objects, then waits for and processes service requests (SRQs) from 
  the IBC-196. 

  Sampler task: Samples sensors at a periodic rate and makes 
  the data available through "telemetry" DataManager items

  Command Monitor task: Monitors "command" DataManager items for
  user requests (e.g. power switch requests) and processes accordingly.

  The following diagram shows how command and telmetry flow through
  the system, from a task architecture viewpoint.

<img src="ibcDataFlow.gif">

<a name="majorClasses"></a>
<b>Major Classes in the framework:</b>

  MicroApp: Created by Main task. Creates other application framework 
  objects. Spawns Sampler and Command Monitor tasks. MicroApp::run()
  executes in the Main task, processes SRQs, gracefully resets the
  application. Subclass IbcApp contains an IbcCardManager object, which in 
  turn contains multiple IbcCard objects added by the application.

  DmMonitor: Monitors "command" DataManager items for updates,
  and processes accordingly. Subclass IbcDmMonitor also contains a pointer to 
  the IbcApp object, monitors and processes changes 
  to command items of individual IbcCard objects contained within the 
  IbcApp's IbcCardManager object.

  MicroSampler: The Sampler task executes the MicroSampler::run() method, 
  which invokes application-specific callbacks at specified rates, which write 
  sensor data to "telemetry" DataManager items. Subclass IbcMicroSampler also 
  contains a pointer to the IbcApp object, invokes
  sampling callbacks of individual IbcCard objects contained within the
  IbcApp's IbcCardManager object.

  TaskSynchronizer: Provides methods for coordination and synchronization
  between Main, Sampler, and Command Monitor tasks.

  IbcCardManager: Contains multiple IbcCard objects. IbcApp creates and 
  contains an instance of IbcCardManager, called "ibc". Application code 
  creates individual IbcCard objects by calling the appropriate 
  add<i>CardType</i>() method of this IbcCardManager object; this method
  instantiates the IbcCard object with the <i>new</i> operator and
  returns the object's pointer to the application. The 
  IbcCardManager object maintains an internal list 
  of all added IbcCard objects. 

  An application contains only one instance of the above classes.

  IbcCard: Abstract class, contains a pointer to the application's 
  Sio32 interface structure, declares pure virtual methods including 
  the following:
<pre>

    processDmChanges()  - If command DM item(s) changed, process command
    sampleMicro()       - Sample micro data and write telemetry DM item(s)
    handleSrq()         - Handle SRQ
    handleResetSrq()    - Handle micro reset SRQ

</pre>
  Subclasses define these methods, 
  encapsulate command and telemetry DataManager items, and other data 
  associated with each type of IBC card. 

  The following diagram shows IbcCard subclasses.

<img src="ibcCardClasses.gif">

  IbcCard objects are not created directly by the application using the
  <i>new</i> operator (the constructors are <i>protected</i>). Rather, the 
  application's IbcApp subclass constructor calls the various 
  add<i>CardType</i>() methods of the IbcApp's IbcCardManager object called 
  "ibc" (IbcCardManager is a <i>friend</i> class 
  of the IbcCard classes). For example, the constructor of an application's
  IbcApp subclass might contain the following:
<pre>

      Gf5vCard *gf5vCard = ibc->addGf5v(Gf5vName, GROUND_FAULT_0_ADDR);

</pre>

  SwitchCard: Note that the abstract SwitchCard subclass of IbcCard itself
  has many subclasses. Some SwitchCard subclasses contain at most one
  SwitchChannel (HpsCard, ExternalSwitch). In these cases, the SwitchCard's
  SwitchChannel is automatically created when the card is instantiated.
  The other SwitchCard subclasses can contain multiple SwitchChannel objects;
  in these cases the application must explicitly add SwitchChannel objects
  to the SwitchCard, using the various addChannel() methods of the subclasses.
  For example, to create a dual-channel VicorCard, 
  the application's IbcApp subclass constructor might look like:
<pre>

    // Create the Vicor 
    VicorCard *vicor = ibc->addVicor(DualVicorName, DUAL_VICOR_0_ADDR, 
				     externalHps->switchChannel(), 
				     LpBusB, Toolsled);

    // Add the two channels to the Vicor
    vicor->addChannel(SwingArmMotorName, 
		      SwingArmMotorPower,
		      SwitchedByFramework,
		      SwitchOff);

    vicor->addChannel(PumpMotorName, 
		      PumpMotorPower,, 
		      SwitchedByFramework,
		      SwitchOff);


</pre>

  SwitchChannel: Represents a power switch. Contained data includes
  switchEntry struct required by "C" ibcLib functions. A SwitchCard object 
  contains one or more SwitchChannel objects. By default, responses to 
  switching commands received by the Command Monitor task are handled 
  automatically by the framework. However, an application
  can override this behavior, if switching is to be done explicitly by
  the application.



  The following diagram illustrates automated command, telemetry, and
  SRQ processing by the framework:
  
<img src="ibcUpdateMechanism.gif">

<b>DataManager Item Names</b>
  IbcCards and components such as SwitchChannels contain associated   
  DataManager items. IbcAppFramework automates the naming of these
  DataManager items. Each IbcApp subclass must supply a <i>systemName</i>
  (e.g., "TIBURON") and <i>appName</i> (e.g., "MWSLED"). The framework 
  concatenates these names, using a '.' delimiter, to form a DataManager name 
  "prefix" (e.g., "TIBURON.MWSLED"). The framework use this prefix to build 
  the names of items contained within IbcCards and components.
  Thus an application does not "hardcode" entire DataManager item names,
  making the application more portable to different environments.

USE
  Steps in writing a new IBC application:

  1) Implement application-specific subclass of IbcApp, 
  adding appropriate methods and data specific to your application.
  Your IbcApp subclass constructor should call the appropriate methods of 
  the IbcCardManager object to add necessary IbcCard objects (other than the 
  CpuCard, which is automatically added by the framework). Thus, your 
  constructor would call methods such as IbcCardManager::addHps(), 
  IbcCardManager::addGf5v(), etc. Your IbcApp subclass should define any 
  "command" and "telemetry" DataManager items which are not included in the 
  IbcCard subclasses.

  2) If your application must respond to user commands which are not
  handled automatically by the IbcCard classes, then you must subclass
  IbcDmMonitor. Your IbcDmMonitor subclass constructor should call  
  DmMonitor::addMonitoredItem() for each "command" DataManager item of 
  your IbcApp subclass. Your subclass should also override 
  IbcDmMonitor::processDmChanges(); the overriding function must
  first call IbcDmMonitor::processDmChanges(), 
  
  3) If your application must generate sampled telemetry which is
  not handled automatically by the IbcCard classes, then you 
  must subclass IbcMicroSampler. Your IbcMicroSampler subclass constructor 
  should start providing the "telemetry" DataManager items of your IbcApp
  subclass defined in step 1. Your subclass should also include
  sampling callbacks, which retrieve sensor data and write it to 
  the "telemetry" DataManager items.

  4) Your IbcApp subclass must override 
  MicroApp::createDmMonitor(). If you defined a subclass of 
  IbcDmMonitor (step 2), createDmMonitor()
  should create and return a pointer to an instance of that subclass;
  otherwise it should create an return a pointer to an instance
  of IbcDmMonitor.

  5) Your IbcApp subclass must override 
  MicroApp::createMicroSampler(). If you defined a subclass of 
  IbcMicroSampler (step 3), createMicroSampler()
  should create and return a pointer to an instance of that subclass;
  otherwise it should create an return a pointer to an instance
  of IbcMicroSampler.

  6) Write a function which instantiates an Sio32Interface object,
  creates an instance of your IbcApp subclass, and then calls 
  that object's run() method.

REFERENCES
<a href="../designReview/index.html">Software Design Review</a>


------------------------------------------------------------------ */
