/* SigLib FIR Filter And Group Delay Example */

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

/* Define constants */
#define	FILE_OUTPUT		0		/* Define as 1 for output to file */
#define	SAMPLE_LENGTH	((SLArrayIndex_t)512)
#define	FILTER_LENGTH	((SLArrayIndex_t)128)
#define	FFT_SIZE		((SLArrayIndex_t)512)
#define	LOG_FFT_SIZE	((SLArrayIndex_t)9)
#define	WINDOW_SIZE		FFT_SIZE

			/* Initialise filter coefficients */
SLData_t	pFilterTaps[FILTER_LENGTH] = {
	-5.34266824816E-0004,  1.24568792546E-0003,  8.73278953630E-0004, 
	 4.37786545396E-0004,  1.57576481250E-0003, -1.38557006660E-0003, 
	 1.90710297624E-0004, -1.85794214656E-0003, -2.00704829381E-0003, 
	 2.40455797115E-0004, -2.04022181601E-0003,  2.71242012844E-0003, 
	 8.82181294290E-0004,  2.06390803758E-0003,  3.46115122350E-0003, 
	-1.75033817834E-0003,  1.86645226647E-0003, -4.19706616768E-0003, 
	-2.84686649762E-0003, -1.38480747151E-0003, -4.84877083488E-0003, 
	 4.15691399504E-0003, -5.59004695862E-0004,  5.33078655121E-0003, 
	 5.64663098926E-0003, -6.64415849217E-0004,  5.54512386900E-0003, 
	-7.26170537971E-0003, -2.32956984257E-0003, -5.38280517195E-0003, 
	-8.92656985171E-0003,  4.46954409718E-0003, -4.72452163230E-0003, 
	 1.05439735389E-0002,  7.10658444744E-0003,  3.43906801399E-0003, 
	 1.19942117579E-0002, -1.02552167173E-0002,  1.37716894902E-0003, 
	-1.31325730564E-0002, -1.39301212180E-0002,  1.64388322268E-0003, 
	-1.37820329052E-0002,  1.81624192809E-0002,  5.87454453127E-0003, 
	 1.37146029376E-0002,  2.30328314183E-0002, -1.17097244170E-0002, 
	 1.26049642763E-0002, -2.87440911303E-0002, -1.98723865258E-0002, 
	-9.90924135116E-0003, -3.58018612026E-0002,  3.19153948705E-0002, 
	-4.50363677305E-0003,  4.55694407950E-0002,  5.19287403766E-0002, 
	-6.69120481527E-0003,  6.26204030713E-0002, -9.50703908154E-0002, 
	-3.71802059842E-0002, -1.13988434152E-0001, -2.98431997465E-0001, 
	 4.24370110064E-0001,  4.24370110064E-0001, -2.98431997465E-0001, 
	-1.13988434152E-0001, -3.71802059842E-0002, -9.50703908154E-0002, 
	 6.26204030713E-0002, -6.69120481527E-0003,  5.19287403766E-0002, 
	 4.55694407950E-0002, -4.50363677305E-0003,  3.19153948705E-0002, 
	-3.58018612026E-0002, -9.90924135116E-0003, -1.98723865258E-0002, 
	-2.87440911303E-0002,  1.26049642763E-0002, -1.17097244170E-0002, 
	 2.30328314183E-0002,  1.37146029376E-0002,  5.87454453127E-0003, 
	 1.81624192809E-0002, -1.37820329052E-0002,  1.64388322268E-0003, 
	-1.39301212180E-0002, -1.31325730564E-0002,  1.37716894902E-0003, 
	-1.02552167173E-0002,  1.19942117579E-0002,  3.43906801399E-0003, 
	 7.10658444744E-0003,  1.05439735389E-0002, -4.72452163230E-0003, 
	 4.46954409718E-0003, -8.92656985171E-0003, -5.38280517195E-0003, 
	-2.32956984257E-0003, -7.26170537971E-0003,  5.54512386900E-0003, 
	-6.64415849217E-0004,  5.64663098926E-0003,  5.33078655121E-0003, 
	-5.59004695862E-0004,  4.15691399504E-0003, -4.84877083488E-0003, 
	-1.38480747151E-0003, -2.84686649762E-0003, -4.19706616768E-0003, 
	 1.86645226647E-0003, -1.75033817834E-0003,  3.46115122350E-0003, 
	 2.06390803758E-0003,  8.82181294290E-0004,  2.71242012844E-0003, 
	-2.04022181601E-0003,  2.40455797115E-0004, -2.00704829381E-0003,
	-1.85794214656E-0003,  1.90710297624E-0004, -1.38557006660E-0003, 
	 1.57576481250E-0003,  4.37786545396E-0004,  8.73278953630E-0004, 
	 1.24568792546E-0003, -5.34266824816E-0004
	};

SLData_t	pFilterState[FILTER_LENGTH];
SLArrayIndex_t	FilterIndex;
SLData_t	*pReal, *pImag, *pMagnitude, *pPhase, *pFFTCoeffs;
SLData_t	ChirpPhase, ChirpValue;
SLData_t	PreviousPhase;

#if	FILE_OUTPUT
FILE	*pOutputFile;
char	fname1[] = "firlpf_t.sig";
char	fname2[] = "firlpf_f.sig";
#endif

void	main(void);

void main(void)
{
	GraphObject *h2DGraph;							/* Declare graph object */

	pReal = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pImag = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pMagnitude = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pPhase = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE);

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("FIR Filter And Group Delay",	/* 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);
	}

													/* Initialise FFT */
	SIF_Fft (pFFTCoeffs,							/* Pointer to FFT coefficients */
			 SIGLIB_NULL_ARRAY_INDEX_PTR,			/* Pointer to bit reverse address table - NOT USED */
			 FFT_SIZE);								/* FFT Size */
													/* Initialise FIR filter */
	SIF_Fir (pFilterState,							/* Pointer to filter state array */
			 &FilterIndex,							/* Pointer to filter index register */
			 FILTER_LENGTH);						/* Filter length */

				/* Generate a linear source signal */
	ChirpPhase = SIGLIB_ZERO;
	ChirpValue = SIGLIB_ZERO;
	SDA_SignalGenerate (pReal,								/* Pointer to destination array */
						SIGLIB_CHIRP_LIN,					/* Signal type - Chirp with linear frequency ramp */
						SIGLIB_ONE,							/* Signal peak level */
						SIGLIB_FILL,						/* Fill (overwrite) or add to existing array contents */
						SIGLIB_ZERO,						/* Signal lower frequency */
						SIGLIB_ZERO,						/* D.C. Offset */
						(SIGLIB_ONE / ((SLData_t)1024.0)),	/* 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 */
				    pReal,							/* 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 ();

#if FILE_OUTPUT
	if ((pOutputFile = fopen(fname1, "wb")) == NULL)
	{
		printf ("Can not open Dat file %s\n", fname1);
		exit (0);
	}
		
	buffer_to_disk (pFilterTaps, pOutputFile, FILTER_LENGTH);

	fclose (pOutputFile);
#endif

	SDA_Fir (pReal,									/* Input array to be filtered */
			pReal,									/* 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 */

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

													/* Perform real FFT */
	SDA_Rfft (pReal,								/* Pointer to real array */
			  pImag,								/* Pointer to imaginary array */
			  pFFTCoeffs,							/* Pointer to FFT coefficients */
			  SIGLIB_NULL_ARRAY_INDEX_PTR,			/* Pointer to bit reverse address table - NOT USED */
			  FFT_SIZE,								/* FFT size */
			  LOG_FFT_SIZE);						/* log2 FFT size */
													/* Calc polar from complex */
	SDA_RectangularToPolar (pReal,					/* Pointer to source real array */
							pImag,					/* Pointer to source imaginary array */
							pMagnitude,				/* Pointer to destination magnitude array */
							pPhase,					/* Pointer to destination phase array */
							FFT_SIZE);				/* Array length */
	SDA_10Log10 (pMagnitude,						/* Pointer to source array */
				 pMagnitude,						/* Pointer to destination array */
				 FFT_SIZE);							/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Spectrum Of Filtered Linear Chirp Signal",	/* Title of the dataset */
				    pMagnitude,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nSpectrum Of Filtered Linear Chirp Signal\nPlease hit <Carriage Return> to continue . . ."); getchar ();

#if FILE_OUTPUT
	if ((pOutputFile = fopen(fname2, "wb")) == NULL)
	{
		printf ("Can not open Dat file %s\n", fname2);
		exit (0);
	}
		
	buffer_to_disk (pMagnitude, pOutputFile, FFT_SIZE);

	fclose (pOutputFile);
#endif

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Phase Of Filtered Linear Chirp Signal",	/* Title of the dataset */
				    pPhase,							/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nPhase Of Filtered Linear Chirp Signal\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	PreviousPhase = SIGLIB_ZERO;
	SDA_GroupDelay (pPhase,							/* Pointer to source array */
					pPhase,							/* Pointer to destination array */
					&PreviousPhase,					/* Pointer to previous phase value */
					SAMPLE_LENGTH);					/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Group Delay Of Filtered Linear Chirp Signal",	/* Title of the dataset */
				    pPhase,							/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nGroup Delay Of Filtered Linear Chirp Signal\n");

	SUF_MemoryFree (pReal);							/* Free memory */
	SUF_MemoryFree (pImag);
	SUF_MemoryFree (pMagnitude);
	SUF_MemoryFree (pPhase);
	SUF_MemoryFree (pFFTCoeffs);
}


