/* SigLib  Frequency Domain Hilbert Transformer Instantaneous Frequency Calculation Example */

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

/* Define constants */
#define TIME_DOMAIN_AS_WELL		0			/* Set to 1 to anable, 0 otherwise */
#define	SAMPLE_LENGTH			((SLArrayIndex_t)512)
#define	FFT_SIZE				((SLArrayIndex_t)512)
#define	LOG_FFT_SIZE			((SLArrayIndex_t)9)

/* Declare arrays and variables */
SLData_t	*pData, *pRealData, *pImagData, *pResults, *pFFTCoeffs;		/* Data array pointers */
SLData_t	ChirpPhase, ChirpValue;
SLData_t	InverseFFTSize;

#if TIME_DOMAIN_AS_WELL
SLData_t	*pFilterTaps, *pFilterState, *delay;
int		FilterIndex;

#define	FILTER_LENGTH	101
#define	DELAY_LENGTH	((FILTER_LENGTH + 1) / 2)
#endif

SLData_t	*pFFTCoeffs;

void	main(void);

void main (void)

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

	pData = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pRealData = SUF_VectorArrayAllocate (FFT_SIZE);
	pImagData = SUF_VectorArrayAllocate (FFT_SIZE);
	pResults = SUF_VectorArrayAllocate (FFT_SIZE);
	pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE);

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Frequency Domain Hilbert Transform",	/* Graph title */
					   "Time / Frequency",			/* 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);
	}


#if TIME_DOMAIN_AS_WELL
	pFilterTaps = SUF_VectorArrayAllocate (FILTER_LENGTH);
	pFilterState = SUF_VectorArrayAllocate (FILTER_LENGTH);
	delay = SUF_VectorArrayAllocate (DELAY_LENGTH);

	SIF_HilbertTransformer (pFilterTaps,			/* Pointer to filter coefficients */
							FILTER_LENGTH);			/* Filter length */
	SIF_Fir (pFilterState,							/* Pointer to filter state array */
			 FilterIndex,							/* Pointer to filter index register */
			 FILTER_LENGTH);						/* Filter length */
	SIF_Delay (delay,								/* Pointer to delay state array */
			   DELAY_LENGTH);						/* Delay length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Filter Coefficients",			/* Title of the dataset */
				    pFilterTaps,					/* Array of Double dataset */
				    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 ("\nFilter Coefficients\nPlease hit <Carriage Return> to continue . . ."); getchar ();
#endif

	SIF_FdHilbert (pFFTCoeffs,						/* Pointer to FFT coefficients */
				   SIGLIB_NULL_ARRAY_INDEX_PTR,		/* Pointer to bit reverse address table */
				   &InverseFFTSize,					/* Inverse FFT size */
				   FFT_SIZE);						/* Hilbert transform size */

	ChirpPhase = SIGLIB_ZERO;
	ChirpValue = SIGLIB_ZERO;

	SDA_SignalGenerate (pData,						/* Pointer to destination array */
						SIGLIB_CHIRP_LIN,			/* Signal type - Chirp with linear frequency ramp */
						((SLData_t)0.45),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)0.025),			/* Signal lower frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						((SLData_t)0.001),			/* Frequency change per sample period */
						SIGLIB_HALF,				/* Signal upper frequency */
						&ChirpPhase,				/* Chirp phase - used for next iteration */
						&ChirpValue,				/* Chirp current value - used for next iteration */
						SAMPLE_LENGTH);				/* Output array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Linear Chirp Signal",			/* Title of the dataset */
				    pData,							/* 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 ("\nLinear Chirp Signal\nPlease hit <Carriage Return> to continue . . ."); getchar ();


						/* Apply frequency domain Hilbert transformerer */
	SDA_FdHilbert (pData,							/* Pointer to source array */
				   pRealData,						/* Pointer to real destination array */
				   pImagData,						/* Pointer to imaginary destination array */
				   pFFTCoeffs,						/* Pointer to FFT coefficients */
				   SIGLIB_NULL_ARRAY_INDEX_PTR,		/* Pointer to bit reverse address table */
				   InverseFFTSize,					/* Inverse FFT size */
				   SAMPLE_LENGTH,					/* Hilbert transform size */
				   LOG_FFT_SIZE);					/* Log2 Hilbert transform size */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Hilbert Transformed Signal",			/* Title of the dataset */
				    pRealData,						/* 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 ("\nHilbert Transformed Signal\nPlease hit <Carriage Return> to continue . . ."); getchar ();

#if TIME_DOMAIN_AS_WELL
	
													/* Apply time domain Hilbert transformerer */
	SDA_Fir (pData,									/* Input array to be filtered */									
			 pRealData,								/* Filtered output array */
			 pFilterState,							/* Pointer to filter state array */
			 pFilterTaps,							/* Pointer to filter coefficients */
			 &FilterIndex,							/* Pointer to filter index register */
			 FILTER_LENGTH,							/* Filter length */
			 SAMPLE_LENGTH);						/* Array length */

	SDA_ShortDelay (pData,							/* Pointer to source array */
					pData,							/* Pointer to destination array */
					delay,							/* Pointer to delay state array */
					DELAY_LENGTH,					/* Delay length */
					SAMPLE_LENGTH);					/* Source array length */

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

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Time Domain Hilbert Transformed",	/* Title of the dataset */
				    pRealData,						/* 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 ("\nTime Domain\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	*pRealData = 1e-6;								/* Ensure non zero values */
	*(pRealData+1) = 1e-6;
#endif

	SDA_InstantFreq (pData,							/* Leading phase input array pointer */
					 pRealData,						/* Lagging phase input array pointer */
					 pResults,						/* Pointer to destination array */
					 FFT_SIZE);						/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Instantaneous Frequency",		/* Title of the dataset */
				    pResults,						/* 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 ("\nInstantaneous Frequency\n");

	SUF_MemoryFree (pData);							/* Free memory */
	SUF_MemoryFree (pRealData);
	SUF_MemoryFree (pImagData);
	SUF_MemoryFree (pResults);
	SUF_MemoryFree (pFFTCoeffs);
}



