#ifndef _IBCCARDMANAGER_H
#define _IBCCARDMANAGER_H

#include "ErrorHandler.h"
#include "IbcComponent.h"
#include "DynamicArray.h"


class IbcApp;
class IbcDmMonitor;
class IbcMicroSampler;
class TaskSynchronizer;
class PowerNameGenerator;

#define IbcPowerSwitch TRUE
#define NormalIsolatedIoLogic FALSE
#define PositiveIsolatedIoLogic TRUE

#define MaxIbcCards 32


/*
CLASS 
IbcCardManager

DESCRIPTION
IbcCardManager contains for IbcCard objects. IbcApp creates and 
contains a pointer to an instance of this class. Application constructor 
then calls methods of this class to add various IbcCard objects and other 
components; the IbcCardManager keeps an internal list of all IbcCards added.
Later, the Command Monitor and Sampler tasks automatically call methods of
IbcCardManager, which in turn call appropriate methods of each IbcCard
object in the list.

AUTHOR
Tom O'Reilly
*/
class IbcCardManager : public ErrorHandler
{
  friend class IbcApp; 
  friend class IbcDmMonitor;
  friend class IbcMicroSampler;

  protected:  

  ///////////////////////////////////////////////////////////////////
  // Constructor
  // [input] systemName: e.g., "TIBURON"
  // [input] appName: e.g., "MWSLED"
  // [input] sio32Channel: Sio32 structure
  // [input] cpuAddress: Address of Cpu card
  IbcCardManager(const char *dmSystemPrefix, 
		 const char *appName,        
		 sio32Chan *sio32Channel,
		 Word cpuAddress);
	      
  ~IbcCardManager();

  public:

  ///////////////////////////////////////////////////////////////////
  // Add an ExternalSwitch
  // [input] name: Name of switch
  // [input] switchReqName: FULL Datamanager name of switch request item
  // [input] switchReqName: FULL Datamanager name of switch status item
  // [input] ibcPower: TRUE if this switch supplies Cpu power
  ExternalSwitch *
    addExternalSwitch(const char *name, 
		      const char *switchReqName,      // FULL Dm name
		      const char *switchStatusName,   // FULL Dm name
		      MBool ibcPower = FALSE);  
  
   
  ///////////////////////////////////////////////////////////////////
  // Add a QuadSerialCard
  // [input] name: Name of card (e.g., "VSP")
  // [input] cardAddr: Address of card
  QuadSerialCard *addQuadSerial(const char *name, Word cardAddr); 


  ///////////////////////////////////////////////////////////////////
  // Add a QuadAtoDCard
  // [input] name: Name of card (e.g., "VSP")
  // [input] cardAddr: Address of card
  // [input] getAtoDCmd: Cmd word to get A-to-D values
  QuadAtoDCard *addQuadAtoD(const char *name, Word cardAddr, 
			    Word getAtoDCmd); 

  ///////////////////////////////////////////////////////////////////
  // Add a Gf5vCard
  // [input] name: Name of card (e.g., "GF5V")
  // [input] cardAddr: Address of card
  Gf5vCard *addGf5v(const char *name, Word cardAddr); 
  
  ///////////////////////////////////////////////////////////////////
  // Add an IsolatedIoCard
  // [input] name: Name of card (e.g., "ISO")
  // [input] cardAddr: Address of card
  // [input] parent: SwitchChannel parent of this card
  // [input] bus: SystemBus on which card SwitchChannels are located 
  // [input] division: LoadDivision for card SwitchChannels
  // [input] positiveLogic: TRUE if card switches use positive logic
  IsolatedIoCard *addIsolatedIo(const char *name,
				Word cardAddr, 
				SwitchChannel *parent,
				SystemBus bus,
				LoadDivision division,
				MBool positiveLogic = FALSE);

  ///////////////////////////////////////////////////////////////////
  // Add an LpsCard 
  // [input] name: Name of card (e.g., "SWINGARMS")
  // [input] cardAddr: Address of card
  // [input] parent: SwitchChannel parent of this card
  // [input] bus: SystemBus on which card SwitchChannels are located
  // [input] division: LoadDivision for card SwitchChannels
  LpsCard *addLps(const char *name, 
		  Word cardAddr,
		  SwitchChannel *parent,
		  SystemBus bus,
		  LoadDivision division);


  ///////////////////////////////////////////////////////////////////
  // Add a VicorLpsCard 
  // [input] name: Name of card (e.g., "SWINGARMS")
  // [input] cardAddr: Address of card
  // [input] parent: SwitchChannel parent of this card
  // [input] bus: SystemBus on which card SwitchChannels are located
  // [input] division: LoadDivision for card SwitchChannels
  // [input] vicorPower: Power allocation for Vicor
  // [input] vicorSwitchMethod: SwitchMethod for Vicor
  // [input] defaultVicorStatus: Default SwitchStatus for Vicor 
  VicorLpsCard *addVicorLps(const char *name,
			    Word cardAddr,
			    SwitchChannel *parent,
			    SystemBus bus,
			    LoadDivision division,
			    Nat16 vicorPower,
			    SwitchMethod vicorSwitchMethod,
			    SwitchStatus defaultVicorStatus);


  ///////////////////////////////////////////////////////////////////
  // Add a HpsCard 
  // [input] name: Name of card (e.g., "TUNGSTEN_LAMP")
  // [input] cardAddr: Address of card
  // [input] parent: SwitchChannel parent of this card
  // [input] power: Power allocation for card switch
  // [input] bus: SystemBus on which card SwitchChannels are located
  // [input] division: LoadDivision for card SwitchChannels
  // [input] switchMethod: SwitchMethod for card switch
  HpsCard *addHps(const char *name, 
		  Word cardAddr,
		  SwitchChannel *parent,
		  Nat16 power, 
		  SystemBus bus,
		  LoadDivision division,
		  SwitchMethod switchMethod);


  ///////////////////////////////////////////////////////////////////
  // Add a VicorCard 
  // [input] name: Name of card (e.g., "SWINGARM_MOTOR")
  // [input] cardAddr: Address of card
  // [input] parent: SwitchChannel parent of this card
  // [input] bus: SystemBus on which card SwitchChannels are located
  // [input] division: LoadDivision for card SwitchChannels
  VicorCard *addVicor(const char *name, 
		      Word cardAddr,
		      SwitchChannel *parent,
		      SystemBus bus,
		      LoadDivision division);


  ///////////////////////////////////////////////////////////////////
  // Generate #define names for switch channels, for use in powerDM.h
  void logPowerMgrNames(const char *filename);

  protected:

  
  ///////////////////////////////////////////////////////////////////
  // Add DM items to monitored group - called by IbcDmMonitor
  // [input] dmMonitor: DmMonitor which monitors items
  STATUS startMonitoring(DmMonitor *dmMonitor);
  
  ///////////////////////////////////////////////////////////////////
  // Build switch entries at start of IbcDmMonitor task.
  // [input] updateSem: DmMonitor's item update semaphore
  // [input] powerStateSem: Semaphore used for power switching
  int buildSwitches(SEM_ID updateSem, SEM_ID powerStateSem);
  
  ///////////////////////////////////////////////////////////////////
  // Handle SRQ from micro; called by Main task.
  // [input] requestCode: SRQ word at head of packet
  // [input] packet: SRQ packet  
  MBool handleSrq(Word requestCode, Byte *packet);

  ///////////////////////////////////////////////////////////////////
  // Call when reset SRQ received; called by Main task.
  // [input] taskSync: Application's TaskSynchronizer
  STATUS handleResetSrq(TaskSynchronizer *taskSync);
  
  ///////////////////////////////////////////////////////////////////
  // Initialize when reset semaphore is given; called by Command Monitor task 
  STATUS handleResetSemaphore();

  ///////////////////////////////////////////////////////////////////
  // If IBC has power switch, return its status. Otherwise return
  // SWITCH_ON. 
  switchStatus powerSwitchStatus();
  
  ///////////////////////////////////////////////////////////////////
  // Process changes to DM items. Called by Command Monitor task.
  STATUS processDmChanges(DmGroup *dmGroup);

  ///////////////////////////////////////////////////////////////////
  // Start providers, set callbacks for micro-sampling. 
  // IbcMicroSampler.
  STATUS startSampling(IbcMicroSampler *sampler);
  
  ///////////////////////////////////////////////////////////////////
  // Sample micro data and update DM items. 
  STATUS sampleMicro(int millisec);
  
  ///////////////////////////////////////////////////////////////////
  // Set switch states to defaults following micro reset
  STATUS resetSwitches();

  ///////////////////////////////////////////////////////////////////
  // Ibc Cpu card, created by IbcCardManager::IbcCardManager()
  CpuCard *cpuCard;

  ///////////////////////////////////////////////////////////////////
  // Return TRUE if IBC cpu is powered by external switch
  MBool hasExternalSwitch();
  
  ///////////////////////////////////////////////////////////////////
  // Array of IbcCards
  DynamicArray cards;

                            
  ///////////////////////////////////////////////////////////////////
  // Add card address to _cardConfig. Return -1 if already have max
  // number of cards, else return 0.
  // [input] address: Address of card
  int addCardAddress(Word address);
  
  const char *_systemName;            // e.g., "TIBURON"
  const char *_appName;               // e.g., "TOOLSLED"
  
  char _appDmPrefix[MaxDmNameLen];
  char _powerDmPrefix[MaxDmNameLen];
  
  sio32Chan *_sio32Chan;



  // Totals of card types; used by lower-level C functions to name
  // DataManager items.
  Int16 _nLpsCards;     // Total of both Lps and VicorLps cards
  Int16 _nHpsCards;
  Int16 _nVicorCards;
  Int16 _nGf5vCards;
  Int16 _nIsolatedIoCards;
  Int16 _nQuadSerialCards;

  ibcCardConfig _cardConfig;

  SwitchChannel *_ibcSwitchChannel;

  PowerNameGenerator *_powerNameGenerator;
};



#endif
