/* SigLib - Early-Late Gate Timing Detector Example

The early late gate synchronizer outputs a continuous stream of zeros except where it detects a pulse,
when it generates a single one pulse.

Loop filters
In many early-late gate synchronizers it is necessary to have separate loop filters for acquisition mode and
tracking mode. This function can support different filter specifications by passing separate filter coefficient
arrays to the function at run time. In tracking mode a wider bandwidth is required to provide a faster transient
response, while tracking mode requires a narrower bandwidth to provide greater stability. The coefficients of
these different filters can be designed using the SIF_LowPassFirFilter function.

Output synchronization delay
The filters within the early-late gate timing error detector cause delays that
effect the timing of the output synchronization pulse so it is important to account for this by delaying the
signal that needs to be sampled. If the signal is complex (I and Q) then both components must be delayed.
*/


#include <stdio.h>
#include <siglib.h>
#include "GraphFunctions.h"

/* Define constants */
#define SQUARE_PULSE			0			/* Set to '1' square pulse input OR '0' for arbitrary pulse shape */
#define PROCESS_ARRAY			0			/* Set to '1' for SDA function OR '0' for SDS_ function */
#define PRBS_INPUT				1			/* Set to '1' for PRBS input OR '0' for square pulse */
#define POSITIVE_PRBS_INPUT		0			/* Set to '1' levels 0 and 1 OR '0' for +/- 1 */
#define BINARY_PRBS_INPUT		1			/* Set to '1' for binary PRBS input OR '0' for four levels */
#define ADD_NOISE				0			/* Set to '1' for add noise OR '0' for no noise */
#define ELG_DEBUG				1			/* Set to '1' to save ELG debug output OR '0' for no debug output */

#define	SAMPLE_LENGTH			((SLArrayIndex_t)512)
#define START_DELAY				((SLArrayIndex_t)15)		/* Arbitrary delay to test synchronizer */

#define	SAMPLE_RATE				((SLData_t)8000.0)			/* Characteristics of PRBS */
//#define SYMBOL_RATE				((SLData_t)1000.0)			/* 8 samples per symbol */
#define SYMBOL_RATE				((SLData_t)400.0)			/* 20 samples per symbol */
//#define SYMBOL_RATE				((SLData_t)200.0)			/* 40 samples per symbol */

#define SYMBOL_LENGTH			((SLFixData_t)(SAMPLE_RATE / SYMBOL_RATE))

#define	GAUS_NOISE_VARIANCE		SIGLIB_FOUR
#define	GAUS_NOISE_OFFSET		SIGLIB_ZERO

#define ELG_EARLY_GATE_DELAY_LENGTH	(SYMBOL_LENGTH >> 1)
#define ELG_LOOP_FILTER_LENGTH		((5 * SYMBOL_LENGTH) + 1)
#define ELG_LOOP_FILTER_FC			(SYMBOL_RATE / SIGLIB_TWO)
#if POSITIVE_PRBS_INPUT
#define ELG_PULSE_DETECTOR_THRESHOLD	((SLData_t)1.0)			/* Threshold below which the timing is not detected */
#else
#define ELG_PULSE_DETECTOR_THRESHOLD	((SLData_t)0.5)			/* Threshold below which the timing is not detected */
#endif
#define ELG_SYNCH_DELAY_ARRAY_LENGTH	(10 * SYMBOL_LENGTH)	/* Length of array for accounting for delay through timing detector */

#if SQUARE_PULSE
SLData_t		ELGMatchedFilterSum;							/* Sum variable for matched comb filter */
#else
SLData_t		*pELGMatchedFilterSignal;						/* One complete symbol used to create matched filter */
SLData_t		*pELGMatchedFilterCoeffs;
#endif
SLData_t		*pELGMatchedFilterState;
SLArrayIndex_t	ELGMatchedFilterIndex;

SLData_t		*pELGEarlyGateDelay;
SLArrayIndex_t	ELGEarlyGateDelayIndex, ELGEarlyGateDelayDepth;

SLData_t		*pELGLoopFilterCoeffs;
SLData_t		*pELGLoopFilterState;
SLArrayIndex_t	ELGLoopFilterIndex;
SLFixData_t		ELGPulseDetectorThresholdFlag;					/* Flag to indicate signal level higher than noise level */
SLData_t		ELGZeroCrossingPreviousSample;					/* Previous sample used for zero crossing detector */
SLArrayIndex_t	ELGTriggerLatency;								/* Estimate of the latency through the ELG TED */
SLArrayIndex_t	ELGTriggerCount;								/* Variables for trigger reverberator */
SLFixData_t		ELGTriggerDetectedFlag;
SLFixData_t		ELGTriggerUpdatedFlag;

SLData_t		*pELGOutputSynchDelay;							/* Output synchronization delay */
SLArrayIndex_t	ELGOutputSynchDelayIndex;

#if ELG_DEBUG
SLData_t LoopFilterOutput[SAMPLE_LENGTH];						/* Arrays for storing output of debug version of early late gate synchronizer */
SLData_t MatchedFilterOutput[SAMPLE_LENGTH];
#endif


/* Declare arrays and variables */
SLData_t	*pSrc, *pTriggerOutput, *pDelayedSrc;				/* Data array pointers */

SLData_t	SrcPhase, PnsCurrentValue;
SLData_t	GaussPhase, GaussValue;


void main (void)

{
	GraphObject *h2DGraph;							/* Declare graph object */

	SLError_t	ErrorCode;
#if PROCESS_ARRAY
#else
	SLArrayIndex_t	i;
#endif

	pSrc = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pDelayedSrc = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pTriggerOutput = SUF_VectorArrayAllocate (SAMPLE_LENGTH);

	pELGMatchedFilterState = SUF_VectorArrayAllocate (SYMBOL_LENGTH);
	pELGEarlyGateDelay = SUF_VectorArrayAllocate (ELG_EARLY_GATE_DELAY_LENGTH);
	pELGLoopFilterCoeffs = SUF_VectorArrayAllocate (ELG_LOOP_FILTER_LENGTH);
	pELGLoopFilterState = SUF_VectorArrayAllocate (ELG_LOOP_FILTER_LENGTH);
	pELGOutputSynchDelay = SUF_VectorArrayAllocate (ELG_SYNCH_DELAY_ARRAY_LENGTH);


	if ((pSrc == NULL) || (pDelayedSrc == NULL) || (pTriggerOutput == NULL) || (pELGMatchedFilterState == NULL) ||
		(pELGEarlyGateDelay == NULL) || (pELGLoopFilterCoeffs == NULL) || (pELGLoopFilterState == NULL) || (pELGOutputSynchDelay == NULL))
	{
		printf ("Memory allocation failure\n");
		exit (0);
	}

#if SQUARE_PULSE
#else
	pELGMatchedFilterSignal = SUF_VectorArrayAllocate (SYMBOL_LENGTH);		/* One complete symbol used to create matched filter */
	pELGMatchedFilterCoeffs = SUF_VectorArrayAllocate (SYMBOL_LENGTH);
	if ((pELGMatchedFilterSignal == NULL) || (pELGMatchedFilterCoeffs == NULL))
	{
		printf ("Memory allocation failure\n");
		exit (0);
	}
#endif


	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Early-Late Gate Timing Detector",	/* Graph title */
					   "Time",						/* X-Axis label */
					   "Magnitude",					/* Y-Axis label */
					   SV_AUTO_SCALE,				/* Scaling mode */
					   SV_SIGNED,					/* Sign mode */
					   SV_GRAPH_LINE,				/* Graph type */
					   "localhost");				/* Graph server */
	if (h2DGraph == NULL)							/* Graph creation failed - e.g is server running ? */
	{
		printf ("\nGraph creation failure. Please check that the server is running\n");
		exit (1);
	}


								/* Initialise the early-late gate synchronizer */
#if SQUARE_PULSE
	ErrorCode =
		SIF_EarlyLateGateSquarePulse (pELGMatchedFilterState,			/* Pointer to matched filter state array */
									  &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
									  &ELGMatchedFilterSum,				/* Pointer to matched filter sum */
									  pELGEarlyGateDelay,				/* Pointer to early gate state array */
									  &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
									  ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
									  pELGLoopFilterState,				/* Pointer to loop filter state array */
									  pELGLoopFilterCoeffs,				/* Pointer to loop filter coefficients */
									  &ELGLoopFilterIndex,				/* Pointer to loop filter index */
									  ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
									  ELG_LOOP_FILTER_FC/SAMPLE_RATE,	/* Loop filter cut-off / centre frequency */
									  &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
									  &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
									  &ELGTriggerCount,					/* Pointer to trigger counter */
									  &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
									  &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
									  SIGLIB_ELG_TRIGGER_MIDDLE,		/* Trigger timing mode */
									  &ELGTriggerLatency,				/* Pointer to trigger latency */
									  SYMBOL_LENGTH);					/* Samples per symbol */
#else
													/* Create signal for matched filter */
	SDA_Fill (pELGMatchedFilterSignal,				/* Pointer to matched filter signal */
			  SIGLIB_ONE,							/* Square pulse */
			  SYMBOL_LENGTH);						/* Samples per symbol */

	ErrorCode =
		SIF_EarlyLateGate (pELGMatchedFilterSignal,			/* Pointer to matched filter signal */
						   pELGMatchedFilterState,			/* Pointer to matched filter state array */
						   pELGMatchedFilterCoeffs,			/* Pointer to matched filter coefficients */
						   &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
						   pELGEarlyGateDelay,				/* Pointer to early gate state array */
						   &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
						   ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
						   pELGLoopFilterState,				/* Pointer to loop filter state array */
						   pELGLoopFilterCoeffs,			/* Pointer to loop filter coefficients */
						   &ELGLoopFilterIndex,				/* Pointer to loop filter index */
						   ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
						   ELG_LOOP_FILTER_FC/SAMPLE_RATE,	/* Loop filter cut-off / centre frequency */
						   &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
						   &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
						   &ELGTriggerCount,				/* Pointer to trigger counter */
						   &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
						   &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
						   SIGLIB_ELG_TRIGGER_MIDDLE,		/* Trigger timing mode */
						   &ELGTriggerLatency,				/* Pointer to trigger latency */
						   SYMBOL_LENGTH);					/* Samples per symbol */
#endif

	if (ErrorCode != SIGLIB_NO_ERROR)
	{
		SUF_MemoryFree (pSrc);						/* Free memory */
		SUF_MemoryFree (pTriggerOutput);
		printf ("SIF_EarlyLateGate returned the error code %x\n", ErrorCode);
		exit(1);
	}

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Loop Filter Coefficients",		/* Title of the dataset */
				    pELGLoopFilterCoeffs,			/* Array of Double dataset */
				    ELG_LOOP_FILTER_LENGTH,			/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nLoop Filter Coefficients\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	SrcPhase = SIGLIB_ZERO;
													/* Clear the destination array so that we can generate a time offset */
	SDA_Clear (pSrc,								/* Pointer to destination array */
			   SAMPLE_LENGTH);				 		/* Array length */

#if PRBS_INPUT
#if POSITIVE_PRBS_INPUT
	SDA_SignalGenerate (pSrc+START_DELAY,			/* Pointer to destination array */
						SIGLIB_PN_SEQUENCE,			/* Signal type - Pseudo random number sequence */
						SIGLIB_TWO,					/* Signal magnitude range */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						SYMBOL_RATE/SAMPLE_RATE,	/* Signal frequency */
						SIGLIB_ZERO,				/* Signal minimum level */
						SIGLIB_TWO,					/* Number of discrete levels in PN sequence */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						&SrcPhase,					/* PRN phase - used for next iteration */
						&PnsCurrentValue,			/* PRN current value - used for next iteration */
						SAMPLE_LENGTH-START_DELAY);	/* Output array length */
#else
#if BINARY_PRBS_INPUT
	SDA_SignalGenerate (pSrc+START_DELAY,			/* Pointer to destination array */
						SIGLIB_PN_SEQUENCE,			/* Signal type - Pseudo random number sequence */
						SIGLIB_TWO,					/* Signal magnitude range */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						SYMBOL_RATE/SAMPLE_RATE,	/* Signal frequency */
						SIGLIB_MINUS_ONE,			/* Signal minimum level */
						SIGLIB_TWO,					/* Number of discrete levels in PN sequence */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						&SrcPhase,					/* PRN phase - used for next iteration */
						&PnsCurrentValue,			/* PRN current value - used for next iteration */
						SAMPLE_LENGTH-START_DELAY);	/* Output array length */
#else
	SDA_SignalGenerate (pSrc+START_DELAY,			/* Pointer to destination array */
						SIGLIB_PN_SEQUENCE,			/* Signal type - Pseudo random number sequence */
						SIGLIB_TWO,					/* Signal magnitude range */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						SYMBOL_RATE/SAMPLE_RATE,	/* Signal frequency */
						SIGLIB_MINUS_ONE,			/* Signal minimum level */
						SIGLIB_FOUR,				/* Number of discrete levels in PN sequence */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						&SrcPhase,					/* PRN phase - used for next iteration */
						&PnsCurrentValue,			/* PRN current value - used for next iteration */
						SAMPLE_LENGTH-START_DELAY);	/* Output array length */
#endif
#endif
#else
	SDA_SignalGenerate (pSrc+START_DELAY,						/* Pointer to destination array */
						SIGLIB_SQUARE_WAVE,						/* Signal type - Square wave */
						SIGLIB_ONE,								/* Signal peak level */
						SIGLIB_FILL,							/* Fill (overwrite) or add to existing array contents */
						(SYMBOL_RATE/SAMPLE_RATE)/SIGLIB_TWO,	/* Signal frequency */
						SIGLIB_ZERO,							/* D.C. Offset */
						SIGLIB_HALF,							/* Duty cycle */
						SIGLIB_ZERO,							/* Signal end value - Unused */
						&SrcPhase,								/* Signal phase - maintained across array boundaries */
						&PnsCurrentValue,						/* Unused */
						SAMPLE_LENGTH-START_DELAY);				/* Output array length */
#endif

#if ADD_NOISE
	GaussPhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pSrc+START_DELAY,				/* Pointer to destination array */
						SIGLIB_GAUSSIAN_NOISE,			/* Signal type - Gaussian noise */
						SIGLIB_ZERO,					/* Signal peak level - Unused */
						SIGLIB_ADD,						/* Fill (overwrite) or add to existing array contents */
						SIGLIB_ZERO,					/* Signal frequency - Unused */
						GAUS_NOISE_OFFSET,				/* D.C. Offset */
						GAUS_NOISE_VARIANCE,			/* Gaussian noise variance */
						SIGLIB_ZERO,					/* Signal end value - Unused */
						&GaussPhase,					/* Pointer to gaussian signal phase - should be initialised to zero */
						&GaussValue,					/* Gaussian signal second sample - should be initialised to zero */
						SAMPLE_LENGTH-START_DELAY);		/* Array length */
#endif

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Source Sequence",				/* Title of the dataset */
				    pSrc,							/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nSource Sequence\nPlease hit <Carriage Return> to continue . . ."); getchar ();


#if PROCESS_ARRAY
#if ELG_DEBUG
#if SQUARE_PULSE
	SDA_EarlyLateGateSquarePulseDebug (pSrc,							/* Pointer to source array */
									   pTriggerOutput,					/* Pointer to trigger output */
									   pELGMatchedFilterState,			/* Pointer to matched filter state array */
									   &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
									   &ELGMatchedFilterSum,			/* Pointer to matched filter sum */
									   pELGEarlyGateDelay,				/* Pointer to early gate state array */
									   &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
									   ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
									   pELGLoopFilterState,				/* Pointer to loop filter state array */
									   pELGLoopFilterCoeffs,			/* Pointer to loop filter coefficients */
									   &ELGLoopFilterIndex,				/* Pointer to loop filter index */
									   ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
									   ELG_PULSE_DETECTOR_THRESHOLD,	/* Noise threshold */
									   &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
									   &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
									   &ELGTriggerCount,				/* Pointer to trigger counter */
									   &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
									   &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
									   MatchedFilterOutput,				/* Pointer to matched filter output */
									   LoopFilterOutput,				/* Pointer to loop filter output */
									   SYMBOL_LENGTH,					/* Samples per symbol */
									   SAMPLE_LENGTH);					/* Source array length */
#else
	SDA_EarlyLateGateDebug (pSrc,							/* Pointer to source array */
							pTriggerOutput,					/* Pointer to trigger output */
							pELGMatchedFilterState,			/* Pointer to matched filter state array */
							pELGMatchedFilterCoeffs,		/* Pointer to matched filter coefficients */
							&ELGMatchedFilterIndex,			/* Pointer to matched filter index */
							pELGEarlyGateDelay,				/* Pointer to early gate state array */
							&ELGEarlyGateDelayIndex,		/* Pointer to early gate delay index */
							ELG_EARLY_GATE_DELAY_LENGTH,	/* Early gate delay length */
							pELGLoopFilterState,			/* Pointer to loop filter state array */
							pELGLoopFilterCoeffs,			/* Pointer to loop filter coefficients */
							&ELGLoopFilterIndex,			/* Pointer to loop filter index */
							ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
							ELG_PULSE_DETECTOR_THRESHOLD,	/* Noise threshold */
							&ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
							&ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
							&ELGTriggerCount,				/* Pointer to trigger counter */
							&ELGTriggerDetectedFlag,		/* Pointer to trigger detected flag */
							&ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
							MatchedFilterOutput,			/* Pointer to matched filter output */
							LoopFilterOutput,				/* Pointer to loop filter output */
							SYMBOL_LENGTH,					/* Samples per symbol */
							SAMPLE_LENGTH);					/* Source array length */
#endif

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Matched Filter Output",		/* Title of the dataset */
				    MatchedFilterOutput,			/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_RED,							/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_ADD);					/* New graph */
	printf ("\nMatched Filter Output\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Loop Filter Output",			/* Title of the dataset */
				    LoopFilterOutput,				/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_GREEN,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_ADD);					/* New graph */
	printf ("\nLoop Filter Output\nPlease hit <Carriage Return> to continue . . ."); getchar ();
#else
#if SQUARE_PULSE
	SDA_EarlyLateGateSquarePulse (pSrc,								/* Pointer to source array */
								  pTriggerOutput,					/* Pointer to trigger output */
								  pELGMatchedFilterState,			/* Pointer to matched filter state array */
								  &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
								  &ELGMatchedFilterSum,				/* Pointer to matched filter sum */
								  pELGEarlyGateDelay,				/* Pointer to early gate state array */
								  &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
								  ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
								  pELGLoopFilterState,				/* Pointer to loop filter state array */
								  pELGLoopFilterCoeffs,				/* Pointer to loop filter coefficients */
								  &ELGLoopFilterIndex,				/* Pointer to loop filter index */
								  ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
								  ELG_PULSE_DETECTOR_THRESHOLD,		/* Noise threshold */
								  &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
								  &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
								  &ELGTriggerCount,					/* Pointer to trigger counter */
								  &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
								  &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
								  SYMBOL_LENGTH,					/* Samples per symbol */
								  SAMPLE_LENGTH);					/* Source array length */
#else
	SDA_EarlyLateGate (pSrc,							/* Pointer to source array */
					   pTriggerOutput,					/* Pointer to trigger output */
					   pELGMatchedFilterState,			/* Pointer to matched filter state array */
					   pELGMatchedFilterCoeffs,			/* Pointer to matched filter coefficients */
					   &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
					   pELGEarlyGateDelay,				/* Pointer to early gate state array */
					   &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
					   ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
					   pELGLoopFilterState,				/* Pointer to loop filter state array */
					   pELGLoopFilterCoeffs,			/* Pointer to loop filter coefficients */
					   &ELGLoopFilterIndex,				/* Pointer to loop filter index */
					   ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
					   ELG_PULSE_DETECTOR_THRESHOLD,	/* Noise threshold */
					   &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
					   &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
					   &ELGTriggerCount,				/* Pointer to trigger counter */
					   &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
					   &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
					   SYMBOL_LENGTH,					/* Samples per symbol */
					   SAMPLE_LENGTH);					/* Source array length */
#endif
#endif
#else
	for (i = 0; i < SAMPLE_LENGTH; i++)
	{
#if SQUARE_PULSE
		pTriggerOutput[i] =
			SDS_EarlyLateGateSquarePulse (pSrc[i],							/* Source data value */
										  pELGMatchedFilterState,			/* Pointer to matched filter state array */
										  &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
										  &ELGMatchedFilterSum,				/* Pointer to matched filter sum */
										  pELGEarlyGateDelay,				/* Pointer to early gate state array */
										  &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
										  ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
										  pELGLoopFilterState,				/* Pointer to loop filter state array */
										  pELGLoopFilterCoeffs,				/* Pointer to loop filter coefficients */
										  &ELGLoopFilterIndex,				/* Pointer to loop filter index */
										  ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
										  ELG_PULSE_DETECTOR_THRESHOLD,		/* Noise threshold */
										  &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
										  &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
										  &ELGTriggerCount,					/* Pointer to trigger counter */
										  &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
										  &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
										  SYMBOL_LENGTH);					/* Samples per symbol */
#else
		pTriggerOutput[i] =
			SDS_EarlyLateGate (pSrc[i],							/* Source data value */
							   pELGMatchedFilterState,			/* Pointer to matched filter state array */
							   pELGMatchedFilterCoeffs,			/* Pointer to matched filter coefficients */
							   &ELGMatchedFilterIndex,			/* Pointer to matched filter index */
							   pELGEarlyGateDelay,				/* Pointer to early gate state array */
							   &ELGEarlyGateDelayIndex,			/* Pointer to early gate delay index */
							   ELG_EARLY_GATE_DELAY_LENGTH,		/* Early gate delay length */
							   pELGLoopFilterState,				/* Pointer to loop filter state array */
							   pELGLoopFilterCoeffs,			/* Pointer to loop filter coefficients */
							   &ELGLoopFilterIndex,				/* Pointer to loop filter index */
							   ELG_LOOP_FILTER_LENGTH,			/* Loop filter length */
							   ELG_PULSE_DETECTOR_THRESHOLD,	/* Noise threshold */
							   &ELGPulseDetectorThresholdFlag,	/* Pointer to pulse detector threshold flag */
							   &ELGZeroCrossingPreviousSample,	/* Pointer to zero crossing previous sample */
							   &ELGTriggerCount,				/* Pointer to trigger counter */
							   &ELGTriggerDetectedFlag,			/* Pointer to trigger detected flag */
							   &ELGTriggerUpdatedFlag,			/* Pointer to trigger updated flag */
							   SYMBOL_LENGTH);					/* Samples per symbol */
#endif
	}
#endif


													/* Initialise the output trigger delay */
	SIF_Delay (pELGOutputSynchDelay,				/* Pointer to delay state array */
			   &ELGOutputSynchDelayIndex,			/* Pointer to delay state index */
			   ELGTriggerLatency);					/* Delay filter length */

													/* Delay trigger output to account for filter delays */
	SDA_Delay (pSrc,								/* Pointer to source array */
			   pDelayedSrc,							/* Pointer to destination array */
			   pELGOutputSynchDelay,				/* Pointer to delay state array */
			   &ELGOutputSynchDelayIndex,			/* Pointer to delay state index */
			   ELGTriggerLatency,					/* Array length */
			   SAMPLE_LENGTH);						/* Sample length */


	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Delayed Source Signal",		/* Title of the dataset */
				    pDelayedSrc,					/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Timing Output",				/* Title of the dataset */
				    pTriggerOutput,					/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_RED,							/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_ADD);					/* New graph */
	printf ("\nDelayed Source Signal And Timing Output\n");

	SUF_MemoryFree (pSrc);							/* Free memory */
	SUF_MemoryFree (pDelayedSrc);

	SUF_MemoryFree (pELGMatchedFilterState);
	SUF_MemoryFree (pELGEarlyGateDelay);
	SUF_MemoryFree (pELGLoopFilterCoeffs);
	SUF_MemoryFree (pELGLoopFilterState);
	SUF_MemoryFree (pELGOutputSynchDelay);

#if SQUARE_PULSE
#else
	SUF_MemoryFree (pELGMatchedFilterSignal);
	SUF_MemoryFree (pELGMatchedFilterCoeffs);
#endif

}

