///////////////////////////////////////////////////////////////////////////////////////
// April 2006 - Separate data collection thread to support SFD, WinRS, WinRS - Saab
// The threading code sits "above" the standard RapiDAQ code in rq.c / rqinternal.c
// The project compiles as a separate stand-alone RQT.dll.  It includes the 
// source files from the SDK directory.  These functions 
// contain common threading support for the two modes of operation and are not
// designed to be called directly from an application.
//
//
// There are two modes of operation: RawCollect and Snapshot.
// 
// RawCollect collects RQ_RawScan data from the card.  The code is in RQRawCollect.c.
// this mode has been developed and tested with a DI unit for WinRS.
//
// Snapshot collects max, min etc. gate data according to the gate's snapshotSelection.  One B scan's
// worth of A scan is also collected according to the selection algorithm.  This mode has been
// developed and tested with a PRX card, firmware 2.x and an InspectionWare application 
// running as an SFD.  The code is in RQSnapshot.c

#ifndef RQTHREAD_H
#define RQTHREAD_H

#include <windows.h>
#include <stdio.h>
#include <io.h>
#include "RQProtected.h"
#include "RQSnapshotInternal.h"
#include "RQCollectInternal.h"
#include "RQTError.h"

#define RQT_PLX_TIMEOUT_FAST 10 // Timeout in mS to wait for plx interrupt if it is possible interrupts are not working
#define RQT_PLX_TIMEOUT_SLOW 1000 // Timeout in mS to wait for plx interrupt when we know interrupts are working
#define RQT_PAUSE_TIME RQT_PLX_TIMEOUT_SLOW  // Time to Sleep in thread when paused
#define RQT_TIME_TO_WAIT_FOR_THREAD (RQT_PAUSE_TIME + 100) // Time to wait for the thread to run.  Must be greater than RQT__TIME_PAUSE or RQT__TIME_PLX_TIMEOUT_SLOW


typedef enum
{
	RQT_SMSPause,
	RQT_SMSCollect,
	RQT_SMSSnapshot,
	RQT_SMSShutdown,
	RQT_SMSNotStarted,
} RQT_StateMachineState;

typedef struct
{
	RQT_StateMachineState currentThreadState;
	RQT_StateMachineState requestedThreadState;
	HANDLE plxSemaphore; 
	unsigned long plxWaitTimeout;
	HANDLE threadHasRun; 
	CRITICAL_SECTION threadCriticalSection;
	unsigned long threadBankSwaps, appBankSwaps;
	RQT_ReturnCode threadExitCode;
	RQT_SnapshotState snapshotState;
	RQT_CollectState collectState;
} RQT_State;

// This creates the capture thread in the 'paused' state
// NB once the capture thread has been created, data capture from the RapiDAQ card must only be via the capture thread
// Must only be called from SnapshotInitialise / RawCollectInitialise
RQ_API NDTS_Boolean RQT_Initialise(unsigned long cardIndex);

// Stop snapshot capture. Must only be called from SnapshotUninitialise / RawCollectUninitialise
RQ_API NDTS_Boolean RQT_Uninitialise(unsigned long cardIndex);

// Sets thread state to start / pause execution.  
// Will block until the thread acknowledges the state change.  This may be up to one second 
// under normal conditions or up to five seconds if the thread can't be contacted.
// A thread should be stopped by calling Uninit, not by setting the state to shutdown.
RQ_API NDTS_Boolean CALL_CONV RQT_SetThreadState(unsigned long cardIndex, RQT_StateMachineState state);

// Requests early bank swap and blocks until the capture thread has completed the bank swap and read the data.
// This MUST NOT be called within an RQ_Lock() as the thread must be allowed to run and do the bank swap.
// Will return immediately with RQT_NoDataAvailable if there is no data in the bank being filled.
NDTS_Boolean CALL_CONV RQT_BankSwapAndUpdate(unsigned long cardIndex);
RQT_State *RQT_ReturnThreadStatePointer(unsigned long cardIndex);

// Function that is run in the thread.
static DWORD WINAPI RQT_ThreadMain(LPVOID lpParameter);

// Called via a hook to RQ_UpdateParameters 
void RQT_UpdateParameters(unsigned long cardIndex);

// Yields the worker thread for card index.
NDTS_Boolean RQT_YieldThread(unsigned long cardIndex) ;
NDTS_Boolean RQT_UpdateDataSamplingStats(unsigned long cardIndex);
enum SRQCaller
{
	SRQThread,
	SRQApp
};
NDTS_Boolean RQT_ServiceRapiDAQ(unsigned long cardIndex, enum SRQCaller caller);
	
#endif
