/*******************************************************************************
*                                                                              *
* Société de Transports de Montréal.                                    	   *
* 2012 - 2013                                                                        *
*                                                                              *
* Projet Zones Tests                                                           *
*                                                                              *
*                                                                              *
*                                                                              *
*******************************************************************************/
/*
	Description:
	Cette classe est un thread qui lit la carte PCI d'I/O sur laquelle sont
	branchées les entrées à haute fréquence.  La machine à états analyse le
	passage du train et détecte les déclenchements (sondes, frotteur négatif,
	pneu porteur).  On utilise un thread car l'analyse doit se faire à très
	haute fréquence sans être ralentie par l'interface graphique.
	
*/

/* ************************************************************************** */
/* Revision:
### YYYMMDD JFM
	Verision d'origine.
	
### YYYYMMDD Description du besoin ou du bug
	Description du changement.
 */

/* ************************************************************************** */

#ifndef ZT1ANALYSISTHREAD_H
#define ZT1ANALYSISTHREAD_H

#define ZT1_ANALYSIS_LOOP_PERIOD 500000	//500 us

#include <QObject>
#include "GlobalDefine.h"
#include "Station.h"
#include <QMutex>
#include "ZTData.h"
#include  "QElapsedTimer"
#include "AnalogInputModule.h"

class CPCIIOMgr;
class CAbstractLazerProbe;

class CZT1AnalysisThread : public QObject
{
	Q_OBJECT
public:
	CZT1AnalysisThread();
	unsigned int Init(CPCIIOMgr *PCIIOHandle,GenericInputMasks_t *InputMasks,CAbstractLazerProbe* PGExtHandle,CAbstractLazerProbe* PGIntHandle,QElapsedTimer *RefTimer,CAnalogInputModule *AnalogInterface);
	void TerminateAnalysis();	//Fonction appelée pour terminer le thread
	bool UpdateDetectionConfig(CZTDetectionFunctionConfig*);	//Mise à jour des fonctions à inhiber
	void SetPGTreshold(qint32 PGTreshold);	//Mise à jour du seuil PG
	bool SetPGCalibration(bool CalibON);	//Démarrer ou arrêter la calibration PG.

private:
	enum eTrainState
	{									//Correspondance d'état dans la documentation
		ZT1_PRE_DETECTION_STATE,
		ZT1_WAIT_FOR_S1_STATE,			//1
		ZT1_S1_ACTIVE_STATE,			//2

		ZT1_S1_TRANSIT_STATE,			//3
		ZT1_S1_TANSIT_MR_STATE,			//3_MR	//After the train type is determined (1st bogie) we cannot change until the train is completely passed
		ZT1_S1_TRANSIT_MPM_STATE,		//3_MPM	//so we need to have 1 seperate state for each type to detect counting errors after the 1st bogie

		ZT1_MR_S1_SECOND_PULSE_STATE,	//4
		ZT1_MR_S2_ACTIVE_STATE,			//5
		ZT1_MR_S2_TRANSIT_STATE,		//6
		ZT1_MR_S2_SECOND_PULSE_STATE,	//7

		ZT1_MPM10_S2_ACTIVE_STATE,		//8
		ZT1_MPM10_S1_SECOND_PULSE_STATE,//9
		ZT1_MPM10_S1_S2_TRAINSIT_STATE, //10
		ZT1_MPM10_S2_SECOND_PULSE_STATE,//11

		ZT1_POST_ANALYSIS_MODE_STATE,	//In this state, we do not analyze in real time, just accumulate data


		ZT1_TRAIN_TRANSIT_FINISHED_STATE

	};

	void RegisterDetection(unsigned int DetectionID, unsigned int Rank, qint64 TimeStamp);

	unsigned int mZT1TrainState;	//état courant de la machine à état
	unsigned int mLastInputs;		//latch du dernier état des entrées discrètes
	qint32 mLastPGIntValue, mLastPGExtValue;	//latch du dernier état des sondes lazer
    int mLastSDFValue;      //latch de lecture du SDF
    bool mExitLoop;			//Flag qui indique si on doit terminer l'analyse
	QMutex mMutex;			//Un mutex pour partager les données entre les threads sans que ça plante
	bool mZT1Analyzing;		//Flag indiquant si le thread roule
	qint32 mPGTreshold;		//Valeur du seuil pneu de guidage
	bool mPGCalibration;	//Flag qui indique si on est présentement en calibration PG
	bool mPEQDetectionLatch;	//Flag nécessaire pour n'enregistrer le déclenchement PEQ1 qu'une seule fois.

	CPCIIOMgr *mPCIInputsHandle;			//Pointeur vers le driver de la carte PCI d'entrées discrètes
	GenericInputMasks_t *mInputMasksPtr;	//Pointeur vers les masques d'entrées
	CAbstractLazerProbe *mPGIntHandle, *mPGExtHandle;	//pointeurs vers le driver des sondes lazer
	CAnalogInputModule *mSDFAnalogInterface; //pointeur vers le driver du module d'acquisition analogique du SDF

	QElapsedTimer *mReferenceTimer;		//pointeur vers le timer d'acquisition

	CZTDetectionFunctionConfig mDetectionConfig;	//Flags qui indiquent quelles fonctions ne doivent pas êtres analysées (configuré dans l'écran Fonction Détections)


public slots:
	void AnalyzeZT1Train();	//La boucle du thread

signals:

    void ZT1DataUpdate(CZT1ThreadData*,bool, int);			//Signal émis au state machine lorsqu'un nouvel échantillon est prêt (à chaque boucle)
	void DetectionTriggered(CZTDetectionData* );		//Signal émis au state machine lorsqu'un déclenchement est détecté
	void NewPGCalibrationData(CZTPGCalibrationData *);	//Signal émis au state machine lorsqu'une donnée de calibration PG est prête
	void NewZT1Flag(int,CZT1FlagsData*);				//Signal émis au state machine lorsqu'une valeur de flag a changé.
	void AddLogString(QString);							//Signal émis pour insérer une ligne au ZTLog
};

#endif // ZT1ANALYSISTHREAD_H
