/* SigLib Arbitrary Length Fast Fourier Transform Example.
This algorithm uses the chirp Z-Transform Algorithm to give a 200
point FFT.
*/

/* Include files */
#include <stdio.h>
#include <siglib.h>
#include <nhl.h>
#include "GraphFunctions.h"

/* Define constants */
#define	SAMPLE_LENGTH	200L						/* Input array length */

/* Declare global variables */
SLData_t			*pInput, *pResults, *pRealData, *pImagData, *pWindowCoeffs, *pRealDatac, *pImagDatac, *pFFTCoeffs;
enum SLArbitraryFFT_t	CZTorFFTSwitch;
SLArrayIndex_t		FFTSize, Log2FFTSize;
SLData_t			*AWNrPtr, *AWNiPtr, *vLrPtr, *vLiPtr, *WMrPtr, *WMiPtr;
SLData_t			*CZTRealWorkPtr, *CZTImagWorkPtr;
SLData_t			InverseFFTSize, InverseSampleLengthXFFTSize;

void main(void);

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

	SLArrayIndex_t	FFTLength = SUF_ArbFftAllocLength (SAMPLE_LENGTH);	/* Calculate the required FFT length */

	printf ("Calculated FFT length = %ld\n", FFTLength);
	printf ("Hit <CR> to continue . . .\n");
	getchar ();

	pInput = SUF_VectorArrayAllocate (SAMPLE_LENGTH);			/* Allocate the memory */
	pWindowCoeffs = SUF_VectorArrayAllocate (SAMPLE_LENGTH);

	pRealData = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pImagData = SUF_VectorArrayAllocate (SAMPLE_LENGTH);

	pRealDatac = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pImagDatac = SUF_VectorArrayAllocate (SAMPLE_LENGTH);

	AWNrPtr = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	AWNiPtr = SUF_VectorArrayAllocate (SAMPLE_LENGTH);

	vLrPtr = SUF_VectorArrayAllocate (FFTLength);
	vLiPtr = SUF_VectorArrayAllocate (FFTLength);

	CZTRealWorkPtr = SUF_VectorArrayAllocate (FFTLength);
	CZTImagWorkPtr = SUF_VectorArrayAllocate (FFTLength);

	WMrPtr = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	WMiPtr = SUF_VectorArrayAllocate (SAMPLE_LENGTH);

	pResults = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pFFTCoeffs = SUF_FftCoefficientAllocate (FFTLength);

	if ((pInput == NULL) || (pWindowCoeffs == NULL) || (pRealData == NULL) || (pImagData == NULL) ||
		(pRealDatac == NULL) || (pImagDatac == NULL) || (AWNrPtr == NULL) || (AWNiPtr == NULL) || 
		(vLrPtr == NULL) || (vLiPtr == NULL) || (CZTRealWorkPtr == NULL) || (CZTImagWorkPtr == NULL) ||
		(WMrPtr == NULL) || (WMiPtr == NULL) || (pResults == NULL) || (pFFTCoeffs == NULL))
	{
		printf ("\n\nMalloc failed\n\n");
		exit (0);
	}

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Arbitrary Length FFT",		/* 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);
	}

													/* Init. arbitrary len. FFT */
	SIF_ArbFft (AWNrPtr,							/* Pointer to AWNr coefficients */
				AWNiPtr,							/* Pointer to AWNi coefficients */
				WMrPtr,								/* Pointer to WMr coefficients */
				WMiPtr,								/* Pointer to WMi coefficients */
				vLrPtr,								/* Pointer to vLr coefficients */
				vLiPtr,								/* Pointer to vLi coefficients */
				pFFTCoeffs,							/* Pointer to FFT coefficients */
				SIGLIB_NULL_ARRAY_INDEX_PTR,		/* Pointer to bit reverse address table */
				&CZTorFFTSwitch,					/* Pointer to switch to indicate CZT or FFT */
				&FFTSize,							/* Pointer to FFT size */
				&Log2FFTSize,						/* Pointer to Log 2 FFT size */
				&InverseFFTSize,					/* Pointer to the inverse FFT size */
				&InverseSampleLengthXFFTSize,		/* Pointer to the inverse (Sample length * FFT size) */
				SAMPLE_LENGTH);						/* Array length */

													/* Generate Hanning window table */
	SIF_Window (pWindowCoeffs,						/* Pointer to window oefficient */
				SIGLIB_HANNING,						/* Window type */
				SIGLIB_ZERO,						/* Window coefficient */
				SAMPLE_LENGTH);						/* Window length */

	read_buffer (pInput, "aa.sig", SAMPLE_LENGTH);	/* Read data from disk */
													/* Apply window to data */
	SDA_Window (pInput,								/* Pointer to source array */
				pInput,								/* Pointer to destination array */
				pWindowCoeffs,						/* Pointer to window oefficients */
				SAMPLE_LENGTH);						/* Window length */

													/* Copy to compare CZT with FT */
	SDA_Copy (pInput,								/* Pointer to source array */
			  pWindowCoeffs,						/* Pointer to destination array */
			  SAMPLE_LENGTH);						/* Array length */

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

													/* Clear the imaginary data input */
	SDA_Clear (pImagDatac,							/* Pointer to destination array */
			   SAMPLE_LENGTH);						/* Array length */

	SDA_ArbCfft (pInput,							/* Pointer to real source array */
				 pImagDatac,						/* Pointer to imaginary source array */
				 pRealData,							/* Pointer to real destination array */
				 pImagData,							/* Pointer to imaginary destination array */
				 CZTRealWorkPtr,					/* Pointer to real temporary array */
				 CZTImagWorkPtr,					/* Pointer to imaginary temporary array */
				 AWNrPtr,							/* Pointer to AWNr coefficients */
				 AWNiPtr,							/* Pointer to AWNi coefficients */
				 WMrPtr,							/* Pointer to WMr coefficients */
				 WMiPtr,							/* Pointer to WMi coefficients */
				 vLrPtr,							/* Pointer to vLr coefficients */
				 vLiPtr,							/* Pointer to vLi coefficients */
				 pFFTCoeffs,						/* Pointer to FFT coefficients */
				 SIGLIB_NULL_ARRAY_INDEX_PTR,		/* Pointer to bit reverse address table */
				 CZTorFFTSwitch,					/* Switch to indicate CZT or FFT */
				 FFTSize,							/* FFT size */
				 Log2FFTSize,						/* Log 2 FFT size */
				 InverseFFTSize,					/* Inverse FFT size */
				 InverseSampleLengthXFFTSize,		/* Inverse (Sample length * FFT size) */
				 SAMPLE_LENGTH);					/* Arbitrary FFT size */

	SDA_Rft (pWindowCoeffs, pRealDatac, pImagDatac, SAMPLE_LENGTH);	/* Perform DFT on copy */
													/* Calculate and display the error */
	SDA_Subtract2 (pRealDatac,						/* Pointer to source array 1 */
				   pRealData,						/* Pointer to source array 2 */
				   pResults,						/* Pointer to destination array */
				   SAMPLE_LENGTH);					/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Real Data Error",				/* 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 ("\nReal Data Error\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	SDA_Subtract2 (pImagDatac,						/* Pointer to source array 1 */
			pImagData,								/* Pointer to source array 2 */
			pResults,								/* Pointer to destination array */
			SAMPLE_LENGTH);							/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Imaginary Data Error",			/* 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 ("\nImaginary Data Error\nPlease hit <Carriage Return> to continue . . ."); getchar ();

				/* Plot chirp z-transform magnitude result */
	SDA_Magnitude (pRealData,						/* Pointer to real source array */
				   pImagData,						/* Pointer to imaginary source array */
				   pResults,						/* Pointer to destination array */
				   SAMPLE_LENGTH);					/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Chirp z-Transform 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 ("\nChirp z-Transform Magnitude\nPlease hit <Carriage Return> to continue . . ."); getchar ();

				/* Plot chirp z-transform phase result */
	SDA_PhaseWrapped (pRealData,					/* Pointer to real source array */
					  pImagData,					/* Pointer to imaginary source array */
					  pResults,						/* Pointer to destination array */
					  SAMPLE_LENGTH);				/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Chirp z-Transform Phase",		/* 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 ("\nChirp z-Transform Phase\nPlease hit <Carriage Return> to continue . . ."); getchar ();

				/* Plot chirp z-transform unwrapped phase result */
	SDA_PhaseUnWrap (pResults,						/* Pointer to source array */
					 pResults,						/* Pointer to destination array */
					 SAMPLE_LENGTH);				/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Chirp z-Transform Unwrapped Phase",	/* 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 ("\nChirp z-Transform Unwrapped Phase\n");

	SUF_MemoryFree (pInput);						/* Free memory */
	SUF_MemoryFree (pWindowCoeffs);
	SUF_MemoryFree (pRealData);
	SUF_MemoryFree (pImagData);
	SUF_MemoryFree (pRealDatac);
	SUF_MemoryFree (pImagDatac);
	SUF_MemoryFree (AWNrPtr);
	SUF_MemoryFree (AWNiPtr);
	SUF_MemoryFree (vLrPtr);
	SUF_MemoryFree (vLiPtr);
	SUF_MemoryFree (CZTRealWorkPtr);
	SUF_MemoryFree (CZTImagWorkPtr);
	SUF_MemoryFree (WMrPtr);
	SUF_MemoryFree (WMiPtr);
	SUF_MemoryFree (pResults);
	SUF_MemoryFree (pFFTCoeffs);

}


