/*******************************************************************************
 *	Control.h	Control process
 *			T.Barnaby,	BEAM Ltd,	2007-02-07
 *******************************************************************************
 */
#ifndef Control_H
#define Control_H	1

#include <stdint.h>
#include <BError.h>
#include <BThread.h>
#include <TmsPuApi.h>
#include <TmsC.h>
#include <TmsEventServerList.h>
#include <Pupe.h>
#include <PupeGeog.h>
#include <BMutex.h>
#include <BRWLock.h>
#include <BSema.h>
#include <main.h>
#include <signal.h>

class Control;

class CycleParams {
public:
				CycleParams(BString cycleType, CycleParam& params);
	BString			cycleType;	// The Cycle type name
	BList<CycleParam>	params;		// Parameters for channels
};

/// A resource test class. this implements a simple timer operated function called every second, that can be used to check on system resources.
class ControlTimer : public BThread {
public:
			ControlTimer(Control& control);
	void		sync();				///< Synchronises timer
	void*		function();
	void		tick();
private:
	Control&		ocontrol;
	BSema			otick;
public:
	static ControlTimer*	timer;
	static void		sigFunc(int sig, siginfo_t* sigInfo, void* data);
};

/// The main system control class
class Control {
public:
			Control(int dbFixed);
			~Control();

	BError		init(int number);			///< Initialise the system
	void		abort();				///< Abort processing

	// Main functionality
	BError		initCmd();
	BError		setProcessPriority(BUInt32 priority);
	BError		configure(BUInt32 ring, ConfigInfo configInfo);	///< Configure the system for use. This includes mapping the individual physical PickUp channels to logical pickup channels.
	BError		test(BList<BError>& errors);
	BError		getStatus(BList<NameValue>& statusList);
	BError		getStatistics(BList<NameValue>& statsList);
	BError		getMasterPuChannel(PuChannel& puChannel);

	BError		addEventServer(BString name);
	BError		delEventServer(BString name);
	BError		setControlInfo(CycleParam params);
	BError		setNextCycle(BUInt32 cycleNumber, BString cycleType);
	BError		getStatus(PuChannel puChannel, PuStatus& puStatus);
	BError		getCycleInformation(BUInt32 cycleNumber, CycleInformation& cycleInformation);
	BError		getData(PuChannel puChannel, DataInfo dataInfo, Data& data, BUInt32& orbitNumber);
	BError		requestData(PuChannel puChannel, DataInfo dataInfo);

	BError		setTestMode(PuChannel puChannel, BUInt32 testOutput, BUInt32 timingDisableMask);
	BError		setTimingSignals(PuChannel puChannel, BUInt32 timingSignals);
	BError		captureDiagnostics(PuChannel puChannel, TestCaptureInfo captureInfo, BArray<BUInt64>& data);
	BError		setTestData(PuChannel puChannel, BInt32 on, BArray<BUInt32> data);	///< This function will set a PU channel to sample data from memory rather than the ADC's
	BError		setPupeConfig(PuChannel puPhysChannel, PupeConfig pupeConfig);
	BError		getPupeConfig(PuChannel puPhysChannel, PupeConfig& pupeConfig);

	void		run();				///< Start the system running
	
	// System utilities
	void		timer();

	void		cycleStart(BUInt32 cycleNumber);		///< The CYCLE_START event has occured
	void		cycleStop(BUInt32 cycleNumber);		///< The CYCLE_STOP event has occured
	void		cycleError(BUInt32 cycleNumber, BError error);	///< A Cycle error occurred
	BError		getPuChannel(PuChannel puPhysChannel, BUInt32& ring, BUInt32& puChannel);
	BError		getPuPhysChannel(BUInt32 ring, BUInt32 puChannel, PuChannel& puPhysChannel);

	int		moduleNum();				///< Returns the module controller number
	
public:
	// General data
	int			osimulate;		///< Simulation mode
	int			osimulateTiming;	///< Simulate timing inputs
	int			osimulateDoubleInjection;///< Simulate a double injection
	BMutex			odmaLock;		///< DMA lock for all PUPE's

private:
	// Low level bits
	BError			initPupeEngines();
	BString			getName();
	BError			mergeError(BError err);

	// Control data
	int			odebugFixed;		///< Fixed debug level from command line
	int			onum;			///< The Module controller number
	int			omaster;		///< The master PUPE
	int			orings;			///< The number of rings serviced
	double			otempInternalMax;	///< Maximum internal temperature
	double			otempFpgaMax;		///< Maximum FPGA temperature
	
	BMutex			olock;			///< Lock for data access
	ControlTimer		otimer;
	int			owatchdog;		///< Watchdog timer
	
	BString			oserverName;		///< The BOAP Servers host name
	BoapServer		oboapServer;		///< The overal Boap server class
	PuControlServer		opuControlServer;	///< The PuControl API interface
	PuProcessServer		opuProcessServer;	///< The PuProcess API interface

	PupeGeog		opupeGeog;		///< The physical location of Pupe boards
	ConfigInfo		oconfigInfo[4];		///< The configuration of PickUp channels
	int			oinitialised[4];	///< The system has been initialised from the ring server

	BMutex			oconfigInfoLock;
	BList<Pupe*>		opupeEngines;		///< The list of PUPE engines
	BRWLock			opupeEnginesLock;
	BMutex			opupeLock;		///< Locks access to the pupe engines
	TmsEventServerList	oeventServers;		///< The list of event servers
	
	BList<CycleParams>	ocycleParms;		///< The table of cycle parameters
	BMutex			ocycleParmsLock;	

	BUInt32			ocycleNumber;		///< The current cycle number
	BString			ocycleType;		///< The current cycle type

	BUInt32			ocycleNumberNext;	///< The next cycle number
	BString			ocycleTypeNext;		///< The next cycle type

	BUInt32			oprocessingCycle;	///< We are processing a cycle
	BUInt32			ocycleTick;		///< Cycle tick for software simulatted timing signals
	
	// Statistics
	double			ostartTime;		///< The start time
	BUInt64			ocycleProcessed;	///< The number of cycles processed
};

#endif
