#ifndef _IBCCOMPONENT_H
#define _IBCCOMPONENT_H

#define LPS_MAX_CHANS 4
#define GF_MAX_CHANS 4

#include "ErrorHandler.h"
#include "DmMonitor.h"
#include "IbcAppError.h"
#include "DynamicArray.h"
#include "SerialDevice.h"
#include "PowerNameGenerator.h"

extern "C" 
{
# include "msgQLib.h"
# include "sio32.h"
# include "sio32Server.h"
# include "sio32Client.h"
# include "microDm.h"
# include "ibcDm.h"
# include "gf_5vDm.h"
# include "quadSerDm.h"
# include "hpsDm.h"
# include "lpsDm.h"
# include "vicorDm.h"
# include "vspDm.h"
};

#define NoSwitchParent NULL

#define ViaSwitchRequest TRUE
#define BypassSwitchRequest FALSE

///////////////////////////////////////////////////////////////////
// SystemBus enumeration
enum SystemBus
{
  HpBusA = A240,
  HpBusB = B240,
  LpBusA = A48,
  LpBusB = B48
};
// Note: Keep enum definitions "parallel" to those in systemBus 


///////////////////////////////////////////////////////////////////
// LoadDivision enumeration
enum LoadDivision
{
  Hotel = HOTEL,
  Lights = LIGHTS,
  Toolsled = TOOLS
};
// Note: Keep enum definitions "parallel" to those in loadDivision


///////////////////////////////////////////////////////////////////
// SwitchMethod enumeration
// []SwitchedByFramework: Framework automatically handles switch requests
// []SwitchedByApp: Application code handles switch requests
enum SwitchMethod
{
  SwitchedByFramework,
  SwitchedByApp
};


///////////////////////////////////////////////////////////////////
// SwitchStatus enumeration
// 
enum SwitchStatus
{
  SwitchNoPower = SWITCH_NO_POWER,
  SwitchOff = SWITCH_OFF,
  SwitchOn = SWITCH_ON,
  SwitchPowerError = SWITCH_POWER_ERROR,
  SwitchOnCascade = SWITCH_ON_CASCADE
};
// Note: Keep enum definitions "parallel" to those in switchStatus



/*
CLASS 
IbcCard

DESCRIPTION
IbcCard represents a card within the IBC. Collection of IbcCard
objects are maintained by an instance of IbcCardManager.
Note that the constructors and destructors of IbcCard classes are
protected; because applications don't create instances directly
with the "new" operator. Rather, IbcCard objects are created by
calling the appropriate add<CardType>() method of the application's
IbcCardManager object.

AUTHOR
Tom O'Reilly
*/
class IbcCard : public ErrorHandler
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] name: Name of card
  // [input] cardAddr: Card address
  // [input] channel: sio32Chan structure 
  IbcCard(const char *name,
	  Word cardAddr,
	  sio32Chan *channel);

  ~IbcCard();

  public:

  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent() = 0;
  
  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  // [input] dmMonitor: DmMonitor which monitors component
  virtual STATUS startMonitoring(DmMonitor *dmMonitor) = 0;

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup) = 0;

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling() = 0;

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro() = 0;

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ. Return TRUE if this IbcCard handles the
  // specified requestCode, else return FALSE.
  virtual MBool handleSrq(Word requestCode, Byte *packet) = 0;

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq() = 0;
  
  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type() = 0;
  
  ///////////////////////////////////////////////////////////////////
  // Indicate if this is a SwitchCard
  virtual MBool isSwitchCard();

  ///////////////////////////////////////////////////////////////////
  // Return name of card
  const char *name();

  ///////////////////////////////////////////////////////////////////
  // Return micro sampling interval (in millisec)
  Nat32 sampleInterval();
  
  ///////////////////////////////////////////////////////////////////
  // Set micro sampling interval
  void setSampleInterval(Nat32 millisec);

  ///////////////////////////////////////////////////////////////////
  // Set system name (e.g., "TIBURON")
  static void setSystemName(const char *systemName);

  ///////////////////////////////////////////////////////////////////
  // Set application name (e.g., "MIDWATER_SLED"). 
  static void setAppName(const char *appName);

  ///////////////////////////////////////////////////////////////////
  // Return system name (e.g., "TIBURON")
  const char *systemName();

  ///////////////////////////////////////////////////////////////////
  // Return application name (e.g., "MIDWATER_SLED")
  const char *appName();
  
  ///////////////////////////////////////////////////////////////////
  // Return card address  
  Word cardAddr();
  

  protected:

  static const char *_systemName;
  static const char *_appName;

  const char *_name;
  const char *_dmPrefix;

  Word _cardAddr;
  sio32Chan *_sio32Chan;

  // Period for micro sampling
  Nat32 _microSampleMillisec;
};



/*
CLASS 
Gf5vCard

DESCRIPTION
Gf5vCard represents a 5-volt Ground-fault card

AUTHOR
Tom O'Reilly
*/
class Gf5vCard : public IbcCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: Name of card (e.g., "GF5V")
  // [input] cardAddr: Card address
  // [input] channel: sio32Chan structure
  // [input] cardNo: Card number. Start at 0, increment for each Gf5vCard 
  // added.
  Gf5vCard(const char *cardName,
	   Word cardAddr, 
	   sio32Chan *channel,
	   Int16 cardNo);

  ~Gf5vCard();

  public:
  
  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type();
  

  ///////////////////////////////////////////////////////////////////
  // Associated DataManager items
  ibcGf5vDmItems dmItems;
};


/*
CLASS 
CpuCard

DESCRIPTION
CpuCard represents the Cpu card

AUTHOR
Tom O'Reilly
*/
class CpuCard : public IbcCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: Name of card (e.g., "CPU")
  // [input] cardAddr: Card address
  // [input] channel: sio32Chan structure
  // [input] cardConfig: IbcCardConfig structure
  CpuCard(const char *cardName,
	  Word cardAddr, 
	  sio32Chan *channel,
	  IbcCardConfig *cardConfig);

  ~CpuCard();


  public:
  
  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type();

  ///////////////////////////////////////////////////////////////////
  // Associated DataManager items
  ibcCpuDmItems dmItems;

  protected:

  ibcCardConfig *_cardConfig;
};



/*
CLASS 
QuadSerialCard 

DESCRIPTION
QuadSerialCard represents a Quad Serial IO Card

AUTHOR
Tom O'Reilly
*/
class QuadSerialCard : public IbcCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: Name of card (e.g., "QUADSERIAL")
  // [input] cardAddr: Card address
  // [input] channel: sio32Chan structure
  // [input] cardNo: Card number. Start at 0, increment for each QuadSerialCard
  // added.
  QuadSerialCard(const char *cardName,
		 Word cardAddr, 
		 sio32Chan *channel,
		 Int16 cardNo);

  ~QuadSerialCard();


  public:
  
  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return card type
  virtual IBC_BoardType type();
  

  ///////////////////////////////////////////////////////////////////
  // Add a SerialDevice to card
  STATUS addDevice(SerialDevice *device, unsigned int channelNo);

  ///////////////////////////////////////////////////////////////////
  // Associated DataManager items
  ibcQuadSerDmItems dmItems;

 protected:

  ///////////////////////////////////////////////////////////////////
  // Array of serial devices (max 4)
  SerialDevice *_serialDevices[4];

};



/*
CLASS 
AtoDChannel

DESCRIPTION
A-to-D channel; Value read from card is Int16;
final scaled output written to Data Manager is Flt32

AUTHOR
Tom O'Reilly
*/

class AtoDChannel
{
  public:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] name: Name of channel (e.g., "PORT_SWINGARM_POSITION")
  // [input] scaleVale: pointer to scaling function. The Int16 value read
  //         from the channel is converted to Flt32 using this function.
  // [input] parent: IbcCard which contains this AtoDChannel
  AtoDChannel(const char *name, 
	      Flt32 (*scaleValue)(Word data),
	      IbcCard *parent);
  
  ~AtoDChannel();
  
  public:

  DmFlt32Object *dmObject;
  Flt32 (*scaleValue)(Word data);
};



/*
CLASS 
QuadAtoDCard

DESCRIPTION
QuadAtoDCard represents a QuadAtoD card, which contains four A-to-D channels.
After creating the QuadAtoDCard, the application adds individual channels
with the addChannel() method.

AUTHOR
Tom O'Reilly
*/
class QuadAtoDCard : public IbcCard
{
  friend class IbcCardManager;

  protected:
  
  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: Name of card (e.g., "QUAD_A_TO_D")
  // [input] cardAddr: Card address
  // [input] channel: sio32Chan structure
  // [input] getAtoDCmd: command word to get A-to-D values  
  QuadAtoDCard(const char *cardName,
	       Word cardAddr, 
	       sio32Chan *channel,
	       Word getAtoDCmd);


  ~QuadAtoDCard();

  public:

  ///////////////////////////////////////////////////////////////////
  // Add an AtoDChannel
  // [input] name: Name of channel (e.g., "PORT_SWINGARM_POSITION")
  // [input] scaleValue: pointer to scaling function. The Int16 value read
  //         from the channel is converted to Flt32 using this function.
  AtoDChannel *addChannel(const char *name, 
			  Flt32 (*scaleValue)(Word data));

  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type();
  

  protected:

  ///////////////////////////////////////////////////////////////////
  // Command word for reading data from micro
  Nat16 _readCmd;
  
  ///////////////////////////////////////////////////////////////////
  // Array of contained AtoDChannels
  DynamicArray _aToDChannels;

  Word _getAtoDCmd;
};




class SwitchCard;
class ExternalSwitch;

/*
CLASS 
SwitchChannel

DESCRIPTION
SwitchChannel represents a power switch.
Contains power switch parameters, as well as a switchEntry struct. 
Note that the switchEntry isn't filled in until the 
SwitchCard::buildSwitch() method is called. This deferral is necessary 
because although the cards and SwitchChannels are created in the 
MicroApp task, the switchEnty structs can only be filled in by the 
DmMonitor task, because the DataManager update semaphore is required.

AUTHOR
Tom O'Reilly
*/
class SwitchChannel
{
  friend class SwitchCard;
  friend class IsolatedIoCard;
  friend class ExternalSwitch;
  
  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] name: Name of SwitchChannel instance
  SwitchChannel(const char *name);

  ~SwitchChannel();

  public:
  
  ///////////////////////////////////////////////////////////////////
  // Name of channel
  const char *name();
  
  ///////////////////////////////////////////////////////////////////
  // Set switch to desired state
  void set(SwitchStatus request, MBool viaSwitchRequest = FALSE);

  ///////////////////////////////////////////////////////////////////
  // Turn switch on
  void switchOn(MBool bypassSwitchRequest = FALSE);

  ///////////////////////////////////////////////////////////////////
  // Turn switch off
  void switchOff(MBool bypassSwitchRequest = FALSE);
  
  ///////////////////////////////////////////////////////////////////
  // Process current switch request
  void processSwitchRequest();
  
  ///////////////////////////////////////////////////////////////////
  // Return current switch request
  SwitchStatus request();

  ///////////////////////////////////////////////////////////////////
  // Return current switch status
  SwitchStatus status();
  
  ///////////////////////////////////////////////////////////////////
  // Return default switch status
  SwitchStatus defaultStatus();
  
  ///////////////////////////////////////////////////////////////////
  // Determine if we have new switch request
  MBool newRequest(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Set DataManager and micro values for switch current warning and
  // alarm thresholds
  // [input] warningThreshold: Warning level
  // [input] alarmThreshold: alarm level
  STATUS setThresholds(Int16 warningThreshold, 
		       Int16 alarmThreshold);

  ///////////////////////////////////////////////////////////////////
  // Set DataManager values for switch current warning and alarm thresholds
  // [input] warningThreshold: Warning level
  // [input] alarmThreshold: alarm level
  STATUS setThresholdsDm(Int16 warningThreshold, 
			 Int16 alarmThreshold);

  ///////////////////////////////////////////////////////////////////
  // Pointer to switchEntry structure
  switchEntry *entry();
  
  protected:
  
  const char *_name;
  MBool _built;
  Word _cardAddr;
  SystemBus _bus;
  Nat16 _power;
  LoadDivision _division;
  SwitchStatus _defaultStatus;
  Nat16 _channelNo;
  SwitchMethod _switchMethod;
  switchEntry *_parent;
    
  ///////////////////////////////////////////////////////////////////
  // switchEntry structure passed to "C" IBC library functions
  switchEntry _entry;
};


/*
CLASS 
SwitchCard

DESCRIPTION
SwitchCard represents a card which contains one or more SwitchChannel
objects.

AUTHOR
Tom O'Reilly
*/
class SwitchCard : public IbcCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor called by ExternalSwitch
  // [input] cardName: name of card
  // [input] channel: Sio32Chan structure
  SwitchCard(const char *cardName,
	     sio32Chan *channel);
  
  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] channel: Sio32Chan structure
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  SwitchCard(const char *cardName,
	     Word cardAddr,
	     sio32Chan *channel,
	     SwitchChannel *parent,  
	     SystemBus bus,
	     LoadDivision division
	     );

  ~SwitchCard();
  

  public:

  ///////////////////////////////////////////////////////////////////
  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel) = 0; 

  ///////////////////////////////////////////////////////////////////
  // Returns TRUE
  virtual MBool isSwitchCard();

  ///////////////////////////////////////////////////////////////////
  // Build internal switchEntry structure of contained SwitchChannel
  // objects.
  virtual STATUS buildSwitch(SEM_ID dmUpdateSem, 
			     SEM_ID powerStatusSem, 
			     PowerNameGenerator *nameGenerator = 0);
  
  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Set switch status to default
  STATUS setDefaultStatus();


  ///////////////////////////////////////////////////////////////////
  // Return number of SwitchChannels on card
  int nSwitchChannels();
  
  ///////////////////////////////////////////////////////////////////
  // Return i-th SwitchChannel, NULL if invalid i specified 
  SwitchChannel *switchChannel(unsigned i);
  
  protected:


  ///////////////////////////////////////////////////////////////////
  // Add a SwitchChannel
  // [input] name: Name of SwitchChannel
  // [input] power: Power allocated to channel
  // [input] switchMethod: SwitchMethod (SwitchedByFramework or SwitchedByApp)
  // [input] channelNo: Channel number. Start at 0, increment for each channel
  // added.
  // [input] parent: Parent SwitchChannel. In the case of VicorLpsCard,
  // the card contains a VicorSwitchChannel which is the parent of four
  // additional SwitchChannels.
  SwitchChannel *addChannel(const char *name,
			    Nat16 power,
			    SwitchMethod switchMethod,
			    SwitchStatus defaultStatus,
			    Nat16 channelNo,
			    SwitchChannel *parent);
  
  ///////////////////////////////////////////////////////////////////
  // Parent of card SwitchChannel object(s)
  SwitchChannel *_parentSwitch;

  ///////////////////////////////////////////////////////////////////
  // SystemBus for card SwitchChannel object(s)
  SystemBus _bus;

  ///////////////////////////////////////////////////////////////////
  // LoadDivision for card SwitchChannel object(s)
  LoadDivision _loadDivision;

  ///////////////////////////////////////////////////////////////////
  // Maximum allowed SwitchChannel objects
  int _maxChannels;
  
  ///////////////////////////////////////////////////////////////////
  // Array of contained SwitchChannel objects
  DynamicArray _switchChannels;
};


/*
CLASS 
MultiSwitchCard

DESCRIPTION
MultiSwitchCard is a SwitchCard which can contain more than one
SwitchChannel.

AUTHOR
Tom O'Reilly
*/
class MultiSwitchCard : public SwitchCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] channel: Sio32Chan structure
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  MultiSwitchCard(const char *cardName,
		  Word cardAddr,
		  sio32Chan *channel,
		  SwitchChannel *parent,  
		  SystemBus bus,
		  LoadDivision division
		  );

  ~MultiSwitchCard();


  public:

  ///////////////////////////////////////////////////////////////////
  // Add a switch channel. Channels should be created with this
  // method in the physical order of the switches on the card.
  // [input] name: Name of SwitchChannel
  // [input] power: Power allocated to SwitchChannel
  // [input] switchMethod: SwitchMethod
  // [input] defaultStatus: SwitchStatus following reset
  SwitchChannel *addChannel(const char *name,
			    Nat16 power,
			    SwitchMethod switchMethod,
			    SwitchStatus defaultStatus);

  protected:

  ///////////////////////////////////////////////////////////////////
  // Parent of channels. For most cases this is the same as the 
  // card parent. But for VicorLpsCard, it is the vicor SwitchChannel.
  SwitchChannel *_channelParent;

  ///////////////////////////////////////////////////////////////////
  // Number of application-added channels.
  int _nAddedChannels;
};


/*
CLASS 
ExternalSwitch

DESCRIPTION
ExternalSwitch represents a SwitchCard external to the IBC

AUTHOR
Tom O'Reilly
*/
class ExternalSwitch : public SwitchCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] switchReqName: Full DataManager name of switch request item
  // [input] switchStatusName: Full DataManager name of switch status item
  // [input] channel: Sio32Chan structure
  ExternalSwitch(const char *cardName,
		 const char *switchReqName,   
		 const char *switchStatusName,
		 sio32Chan *channel);

  ~ExternalSwitch();

  public:

  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro 
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Build internal switchEntry structure
  virtual STATUS buildSwitch(SEM_ID dmUpdateSem, 
			     SEM_ID powerStatusSem,
			     PowerNameGenerator *nameGenerator = 0);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel); 

  ///////////////////////////////////////////////////////////////////
  // Return card type
  IBC_BoardType type();
  
  ///////////////////////////////////////////////////////////////////
  // Return pointer to contained SwitchChannel object
  SwitchChannel *switchChannel();
  

  protected:
  
  const char *_switchReqName;
  const char *_switchStatusName;

  SwitchChannel *_switchChannel;
};


/*
CLASS 
LpsCard

DESCRIPTION
LpsCard represents a low-power switch card without a Vicor. After
creating the LpsCard, up to four SwitchChannel objects can be added to 
it with MultiSwitchCard::addChannel(). 

AUTHOR
Tom O'Reilly
*/
class LpsCard: public MultiSwitchCard
{
  friend class IbcCardManager;

  protected:
  
  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] channel: Sio32Chan structure
  // [input] cardNo: Card number. Start at 0, increment for each LpsCard added.
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  LpsCard(const char *cardName,
	  Word cardAddr,
	  sio32Chan *channel,
	  Int16 cardNo,
	  SwitchChannel *parent,         // NULL if no parent
	  SystemBus bus,
	  LoadDivision division);

  ~LpsCard();


  public:

  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();
  
  ///////////////////////////////////////////////////////////////////
  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel);

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type();

  ///////////////////////////////////////////////////////////////////
  // Associated DataManager items
  ibcLpsDmItems dmItems;

};


/*
CLASS 
VicorLpsCard

DESCRIPTION
VicorLpsCard represents a low-power switch card with a Vicor. Contains
a SwitchChannel object representing the Vicor, which is automatically
created by the constructor. After creating the LpsCard, up to four 
SwitchChannel objects should be added to it with 
MultiSwitchCard::addChannel(). 

AUTHOR
Tom O'Reilly
*/
class VicorLpsCard : public LpsCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] channel: Sio32Chan structure
  // [input] cardNo: Card number. Start at 0, increment for each VicorLpsCard 
  // added.
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  // [input] vicorPower: Power allocation for card's Vicor (for PowerManager)
  // [input] switchMethod: SwitchMethod for card's Vicor
  // [input] defaultStatus: SwitchStatus following reset
  VicorLpsCard(const char *cardName,
	       Word cardAddr,
	       sio32Chan *channel,
	       Int16 cardNo,
	       SwitchChannel *parent,         // NULL if no parent
	       SystemBus bus,
	       LoadDivision division,
	       Nat16 vicorPower,
	       SwitchMethod switchMethod,
	       SwitchStatus defaultStatus);

  ~VicorLpsCard();

  public:

  ///////////////////////////////////////////////////////////////////
  // Enable card Vicor
  void enableVicor();

  ///////////////////////////////////////////////////////////////////
  // Disable card Vicor
  void disableVicor();
  
  ///////////////////////////////////////////////////////////////////
  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel); 

  protected:

  ///////////////////////////////////////////////////////////////////
  // SwitchChannel of card Vicor
  SwitchChannel *_vicor;
};


/*
CLASS 
HpsCard

DESCRIPTION
HpsCard represents a high-power switch card. HpsCard contains one
SwitchChannel, which is automatically created in the constructor.

AUTHOR
Tom O'Reilly
*/
class HpsCard : public SwitchCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] channel: Sio32Chan structure
  // [input] cardNo: Card number. Start at 0, increment for each HpsCard added.
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] power: Power allocated to card (for PowerManager)
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  // [input] switchMethod: SwitchMethod
  HpsCard(const char *cardName,
	  Word cardAddr,
	  sio32Chan *channel,
	  Int16 cardNo,
	  SwitchChannel *parent,         // NULL if no parent
	  Nat16 power,
	  SystemBus bus,
	  LoadDivision division,
	  SwitchMethod switchMethod);

  ~HpsCard();

  public:
  
  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel);

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type();

  ///////////////////////////////////////////////////////////////////
  // Associated DataManager items
  ibcHpsDmItems dmItems;  

  ///////////////////////////////////////////////////////////////////
  // Turn switch on
  void switchOn(MBool usePowerMgr = FALSE);

  ///////////////////////////////////////////////////////////////////
  // Turn switch off
  void switchOff(MBool usePowerMgr = FALSE);

  ///////////////////////////////////////////////////////////////////
  // Process switch request
  void processSwitchRequest();
  
  ///////////////////////////////////////////////////////////////////
  // Return TRUE if there is a new switch request
  MBool newRequest(DmGroup *dmGroup);
  
  protected:
  
  SwitchChannel *_switchChannel;
};


/*
CLASS 
VicorCard

DESCRIPTION
VicorCard represents a single or dual Vicor card. After creating the 
VicorCard, up to two SwitchChannel objects can be added to it with 
MultiSwitchCard::addChannel(). 

AUTHOR
Tom O'Reilly
*/
class VicorCard : public MultiSwitchCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] channel: Sio32Chan structure
  // [input] cardNo: Card number. Start at 0, increment for each VicorCard 
  // added.
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  VicorCard(const char *cardName,
	    Word cardAddr,
	    sio32Chan *channel,
	    Int16 cardNo,
	    SwitchChannel *parent,         // NULL if no parent
	    SystemBus bus,
	    LoadDivision division);

  ~VicorCard();

  public:
  
  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel);

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return type
  virtual IBC_BoardType type();

  ///////////////////////////////////////////////////////////////////
  // Associated DataManager items
  vicorDmItems dmItems[2];
};



/*
CLASS 
DigitalOutput

DESCRIPTION
DigitalOutput represents a switch on an IsolatedIoCard. The
DigitalOutput has an associated Boolean Datamanager item; when
the item changes the switch is closed or opened accordingly. 

AUTHOR
Tom O'Reilly
*/
class DigitalOutput
{
  public:
  
  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] systemPrefix: e.g., "TIBURON"
  // [input] appName: e.g., "MWSLED"
  // [input] outputName: name of DigitalOutput object
  // [input] channelNo: DigitalOutput number on card. Start at 0, increment
  // for each DigitalOutput added to card.
  // [input] switchMethod: SwitchMethod
  DigitalOutput(const char *systemPrefix,
		const char *appName,
		const char *outputName,
		int channelNo,
		SwitchMethod switchMethod);

  ~DigitalOutput();

  ///////////////////////////////////////////////////////////////////
  // Return name of output
  const char *name();  

  ///////////////////////////////////////////////////////////////////
  // Return SwitchMethod
  SwitchMethod switchMethod();

  ///////////////////////////////////////////////////////////////////
  // Return channel number
  Nat16 channelNo();
  
  ///////////////////////////////////////////////////////////////////
  // Associated DataManager item
  DM_Item dmItem;

  protected:

  char *_name;
  int _switchChannelNo;
  SwitchMethod _switchMethod;
};


/*
CLASS 
IsolatedIoCard

DESCRIPTION
IsolatedIoCard represents an isolated IO card. After constructing
the IsolatedIoCard, a total of eight DigitalOutput and
SwitchChannel objects can be added to it with addOutput() and
addChannel().

AUTHOR
Tom O'Reilly
*/
class IsolatedIoCard : public MultiSwitchCard
{
  friend class IbcCardManager;

  protected:

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] cardName: name of card
  // [input] cardAddr: Address of card
  // [input] cardNo: Card number. Start at 0, increment for each IsolatedIoCard
  // added.
  // [input] parent: Parent SwitchChannel, NULL if no parent
  // [input] bus: SystemBus of SwitchCard
  // [input] division: LoadDivision (for PowerManager)
  // [input] positiveLogic: If TRUE, card type is ISOLATED_IO_POS_TRUE,
  // else type is ISOLATED_IO
  IsolatedIoCard(const char *cardName,
		 Word cardAddr,
		 sio32Chan *channel,
		 Int16 cardNo,
		 SwitchChannel *parent, 
		 SystemBus bus,
		 LoadDivision division,
		 MBool positiveLogic = FALSE);
  

  ~IsolatedIoCard();

  public:

  ///////////////////////////////////////////////////////////////////
  // Add a switch channel. Channels (and outputs) should be created 
  // in the physical order of the switches on the card.
  SwitchChannel *addChannel(const char *name,
			    Nat16 power,
			    SwitchMethod switchMethod,
			    SwitchStatus defaultStatus);

  ///////////////////////////////////////////////////////////////////
  // Add DigitalOutput, which has an associated Boolean item,
  // but NOT a switchEntry. Outputs (and channels) should be created 
  // in the physical order of the switches on the card.
  DigitalOutput *addOutput(const char *name, 
			   SwitchMethod switchMethod);

  ///////////////////////////////////////////////////////////////////
  // Initialize DM items and micro
  virtual STATUS handleResetEvent();

  ///////////////////////////////////////////////////////////////////
  // Connect application and power manager switch items
  virtual STATUS connectSwitchItems(SwitchChannel *channel);

  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group
  virtual STATUS startMonitoring(DmMonitor *dmMonitor);

  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items
  virtual STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providing telemetry DataManager items
  virtual STATUS startSampling();

  ///////////////////////////////////////////////////////////////////
  // Read micro and update DM items
  virtual STATUS sampleMicro();

  ///////////////////////////////////////////////////////////////////
  // Call after receiving SRQ
  virtual MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call after receiving reset SRQ
  virtual STATUS handleResetSrq();

  ///////////////////////////////////////////////////////////////////
  // Return card type
  IBC_BoardType type();

  protected:

  ///////////////////////////////////////////////////////////////////
  // Array of DigitalOutput objects  
  DynamicArray _outputs;

  ///////////////////////////////////////////////////////////////////
  // Card type is either ISOLATED_IO or ISOLATED_IO_POS_TRUE
  IBC_BoardType _cardType;
};


#endif
