/* SigLib Complex FIR Filter Example */

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

/* Define constants */
#define	FILTER_LENGTH	((SLArrayIndex_t)64)
#define	SAMPLE_LENGTH	((SLArrayIndex_t)512)
#define	FFT_SIZE		((SLArrayIndex_t)512)
#define	LOG_FFT_SIZE	((SLArrayIndex_t)9)

			/* Initialise filter coefficients */
SLData_t	pRealFilterTaps[FILTER_LENGTH] = {
	-3.783E-3,  2.803E-3,  2.648E-3,  2.891E-3,  3.397E-3,  4.094E-3, 
 	 4.942E-3,  5.917E-3,  7.005E-3,  8.196E-3,  9.479E-3,  1.084E-2, 
 	 1.229E-2,  1.379E-2,  1.535E-2,  1.695E-2,  1.857E-2,  2.021E-2, 
 	 2.183E-2,  2.344E-2,  2.500E-2,  2.651E-2,  2.795E-2,  2.929E-2, 
 	 3.053E-2,  3.165E-2,  3.264E-2,  3.348E-2,  3.417E-2,  3.469E-2, 
 	 3.504E-2,  3.522E-2,  3.522E-2,  3.504E-2,  3.469E-2,  3.417E-2, 
 	 3.348E-2,  3.264E-2,  3.165E-2,  3.053E-2,  2.929E-2,  2.795E-2, 
 	 2.651E-2,  2.500E-2,  2.344E-2,  2.183E-2,  2.021E-2,  1.857E-2, 
 	 1.695E-2,  1.535E-2,  1.379E-2,  1.229E-2,  1.084E-2,  9.479E-3, 
 	 8.196E-3,  7.005E-3,  5.917E-3,  4.942E-3,  4.094E-3,  3.397E-3, 
 	 2.891E-3,  2.648E-3,  2.803E-3, -3.783E-3
	};

SLData_t	pImagFilterTaps[FILTER_LENGTH] = {
	-3.783E-3,  2.803E-3,  2.648E-3,  2.891E-3,  3.397E-3,  4.094E-3, 
 	 4.942E-3,  5.917E-3,  7.005E-3,  8.196E-3,  9.479E-3,  1.084E-2, 
 	 1.229E-2,  1.379E-2,  1.535E-2,  1.695E-2,  1.857E-2,  2.021E-2, 
 	 2.183E-2,  2.344E-2,  2.500E-2,  2.651E-2,  2.795E-2,  2.929E-2, 
 	 3.053E-2,  3.165E-2,  3.264E-2,  3.348E-2,  3.417E-2,  3.469E-2, 
 	 3.504E-2,  3.522E-2,  3.522E-2,  3.504E-2,  3.469E-2,  3.417E-2, 
 	 3.348E-2,  3.264E-2,  3.165E-2,  3.053E-2,  2.929E-2,  2.795E-2, 
 	 2.651E-2,  2.500E-2,  2.344E-2,  2.183E-2,  2.021E-2,  1.857E-2, 
 	 1.695E-2,  1.535E-2,  1.379E-2,  1.229E-2,  1.084E-2,  9.479E-3, 
 	 8.196E-3,  7.005E-3,  5.917E-3,  4.942E-3,  4.094E-3,  3.397E-3, 
 	 2.891E-3,  2.648E-3,  2.803E-3, -3.783E-3
	};

SLData_t		RealFilterState[FILTER_LENGTH], ImagFilterState[FILTER_LENGTH];
SLArrayIndex_t	FilterIndex;
SLData_t		*pRealData, *pImagData, *pResults, *pFFTCoeffs;
SLData_t		ChirpPhase, ChirpValue;

void	main(void);

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

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

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Complex FIR Filter",		/* 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 */

	SIF_ComplexFir (RealFilterState, ImagFilterState, &FilterIndex, FILTER_LENGTH);

													/* Generate a broadband complex signal */
	ChirpPhase = SIGLIB_ZERO;
	ChirpValue = SIGLIB_ZERO;
	SDA_SignalGenerate (pRealData,					/* 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.00005),		/* Signal lower frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						((SLData_t)0.0005),			/* 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 */
	ChirpPhase = SIGLIB_ZERO;
	ChirpValue = SIGLIB_ZERO;
	SDA_SignalGenerate (pImagData,					/* 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.00005),		/* Signal lower frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						((SLData_t)0.0005),			/* 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 */

													/* Frequency domain calculation */
													/* Perform complex source data FFT */
	SDA_Cfft (pRealData,							/* Pointer to real array */
			pImagData,								/* 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 */

													/* Calculate real power from complex */
	SDA_LogMagnitude (pRealData,					/* Pointer to real source array */
					  pImagData,					/* Pointer to imaginary source array */
					  pResults,						/* Pointer to log magnitude destination array */
					  SAMPLE_LENGTH);				/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Input Signal FFT Magnitude",	/* Title of the dataset */
				    pResults,						/* 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 ("\nInput Signal FFT Magnitude\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Generate a broadband complex signal */
	ChirpPhase = SIGLIB_ZERO;
	ChirpValue = SIGLIB_ZERO;

	SDA_SignalGenerate (pRealData,					/* 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.00005),		/* Signal lower frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						((SLData_t)0.0005),			/* 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 */

	ChirpPhase = SIGLIB_ZERO;
	ChirpValue = SIGLIB_ZERO;

	SDA_SignalGenerate (pRealData,					/* 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.00005),		/* Signal lower frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						((SLData_t)0.0005),			/* 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 */

				/* Apply complex fir filter */
	SDA_ComplexFir (pRealData,						/* Real input array pointer */
					pImagData,						/* Imaginary input array pointer */
					pRealData,						/* Pointer to real destination array */
					pImagData,						/* Pointer to imaginary destination array */
					RealFilterState,				/* Real state array pointer */
					ImagFilterState,				/* Imaginary state array pointer */
					pRealFilterTaps,				/* Real coefficient array pointer */
					pImagFilterTaps,				/* Imaginary coefficient array pointer */
					&FilterIndex,					/* Filter index */
					FILTER_LENGTH,					/* Filter length */
					SAMPLE_LENGTH);					/* Array length */


													/* Frequency domain calculation */
													/* Perform complex source data FFT */
	SDA_Cfft (pRealData,							/* Pointer to real array */
			pImagData,								/* 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 */

													/* Calculate real power from complex */
	SDA_LogMagnitude (pRealData,					/* Pointer to real source array */
					  pImagData,					/* Pointer to imaginary source array */
					  pResults,						/* Pointer to log magnitude destination array */
					  SAMPLE_LENGTH);				/* Array length */

													/* Plot FFT magnitude result */
	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Output Signal FFT Magnitude",	/* Title of the dataset */
				    pResults,						/* 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 ("\nOutput Signal FFT Magnitude\n");

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


