/* SigLib Costas Loop Example */ #include #include #include #include #include "GraphFunctions.h" /* Define constants */ #define PER_SAMPLE 0 /* Set to '1' to use SDS_CostasLoop, '0' to use SDA_CostasLoop */ #define SAMPLE_LENGTH 512L #define SAMPLE_RATE ((SLData_t)48000.0) /* Sample rate */ #define CARRIER_FREQUENCY ((SLData_t)300.0) /* Carrier frequency */ #define FEEDBACK_MODE SIGLIB_COSTAS_LOOP_MULTIPLY_LOOP /* Feedback mode */ //#define FEEDBACK_MODE SIGLIB_COSTAS_LOOP_POLARITY_LOOP //#define FEEDBACK_MODE SIGLIB_COSTAS_LOOP_HARD_LIMITED_LOOP /* Very sensitive so may need to reduce modulation index */ /* Note : Costas loop LPFs - lengths are chosen so that there are at least two full cycles and an odd number - for an integer group delay */ #define COSTAS_LP_LPF_LENGTH (((SLFixData_t)((SAMPLE_RATE / CARRIER_FREQUENCY) * SIGLIB_TWO)) | 0x1) /* Costas loop LP LPF FIR filter length */ #define COSTAS_LP_LPF_CUTOFF_FREQUENCY 100.0 /* LPF cut-off frequency */ #define COSTAS_LP_VCO_MODULATION_INDEX ((SLData_t)0.005) /* Modulation index */ #define COSTAS_LP_LOOP_FILTER_ALPHA ((SLData_t)0.9) /* Feedback coeff for one-pole loop filter */ #define COSTAS_LP_VCO_SINE_TABLE_SIZE ((SLArrayIndex_t)1024) /* Look up table for fast sine calculation */ SLData_t *pData; SLData_t *pCostasLpLPFCoeffs, *pCostasLpLPF1State, *pCostasLpLPF2State; /* Costas loop loop filter coefficient pointer */ SLArrayIndex_t CostasLpLPF1Index; /* Costas loop inphase LPF filter index */ SLArrayIndex_t CostasLpLPF2Index; /* Costas loop quadrature phase LPF filter index */ SLData_t CostasLpState; /* Costas loop feedback state for next iteration */ SLData_t CostasLpLoopFilterState; /* Costas loop loop filter feedback coeff */ SLData_t *pCostasLpVCOLookUpTable; /* VCO cosine look-up-table pointer */ SLData_t CostasLpVCOPhase; /* Costas loop VCO phase */ SLData_t SinePhase; void main (void); void main(void) { GraphObject *h2DGraph; /* Declare graph object */ #if PER_SAMPLE SLArrayIndex_t i; #endif printf ("\n\nSigLib Costas Loop Example\n"); pData = SUF_VectorArrayAllocate (SAMPLE_LENGTH); pCostasLpLPFCoeffs = SUF_VectorArrayAllocate (COSTAS_LP_LPF_LENGTH); pCostasLpLPF1State = SUF_VectorArrayAllocate (COSTAS_LP_LPF_LENGTH); pCostasLpLPF2State = SUF_VectorArrayAllocate (COSTAS_LP_LPF_LENGTH); pCostasLpVCOLookUpTable = SUF_CostasLoopVCOArrayAllocate (COSTAS_LP_VCO_SINE_TABLE_SIZE); SIF_CostasLoop (&CostasLpVCOPhase, /* VCO phase */ pCostasLpVCOLookUpTable, /* VCO look up table */ COSTAS_LP_VCO_SINE_TABLE_SIZE, /* VCO look up table size */ COSTAS_LP_LPF_CUTOFF_FREQUENCY / SAMPLE_RATE, /* Low-pass filter cut-off frequency */ pCostasLpLPF1State, /* Pointer to loop filter 1 state */ &CostasLpLPF1Index, /* Pointer to loop filter 1 index */ pCostasLpLPF2State, /* Pointer to loop filter 2 state */ &CostasLpLPF2Index, /* Pointer to loop filter 2 index */ pCostasLpLPFCoeffs, /* Pointer to loop filter coefficients */ COSTAS_LP_LPF_LENGTH, /* Loop filter length */ &CostasLpLoopFilterState, /* Pointer to loop filter state */ &CostasLpState); /* Pointer to delayed sample */ SinePhase = ((SLData_t)2.0); /* Arbitrary phase - radians */ h2DGraph = /* Initialize graph */ Create2DGraph ("Costas Loop", /* 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); } do { SDA_SignalGenerate (pData, /* Pointer to destination array */ SIGLIB_SINE_WAVE, /* Signal type - Sine wave */ SIGLIB_ONE, /* Signal peak level */ SIGLIB_FILL, /* Fill (overwrite) or add to existing array contents */ CARRIER_FREQUENCY / SAMPLE_RATE, /* Signal frequency */ SIGLIB_ZERO, /* D.C. Offset */ SIGLIB_ZERO, /* Unused */ SIGLIB_ZERO, /* Signal end value - Unused */ &SinePhase, /* Signal phase - maintained across array boundaries */ SIGLIB_NULL_DATA_PTR, /* Unused */ SAMPLE_LENGTH); /* Output array length */ Display2DGraph (h2DGraph, /* Graph handle */ "Original Sine Wave", /* Title of the dataset */ pData, /* Array of Double dataset */ SAMPLE_LENGTH, /* Number of data points */ SV_GRAPH_LINE, /* Graph type */ SV_MAGENTA, /* Colour */ SV_HIDE_MARKERS, /* Marker enable / disable */ SV_GRAPH_NEW); /* New graph */ #if PER_SAMPLE for (i = 0; i < SAMPLE_LENGTH; i++) { *(pData +i) = SDS_CostasLoop (*(pData +i), /* Source data sample */ &CostasLpVCOPhase, /* VCO phase */ COSTAS_LP_VCO_MODULATION_INDEX, /* VCO modulation index */ pCostasLpVCOLookUpTable, /* VCO look up table */ COSTAS_LP_VCO_SINE_TABLE_SIZE, /* VCO look up table size */ CARRIER_FREQUENCY / SAMPLE_RATE, /* Carrier frequency */ pCostasLpLPF1State, /* Pointer to loop filter 1 state */ &CostasLpLPF1Index, /* Pointer to loop filter 1 index */ pCostasLpLPF2State, /* Pointer to loop filter 2 state */ &CostasLpLPF2Index, /* Pointer to loop filter 2 index */ pCostasLpLPFCoeffs, /* Pointer to loop filter coefficients */ COSTAS_LP_LPF_LENGTH, /* Loop filter length */ &CostasLpLoopFilterState, /* Pointer to loop filter state */ COSTAS_LP_LOOP_FILTER_ALPHA, /* Loop filter coefficient */ FEEDBACK_MODE, /* Loop feedback mode */ &CostasLpState); /* Pointer to delayed sample */ } #else SDA_CostasLoop (pData, /* Source data pointer */ pData, /* Destination data pointer */ &CostasLpVCOPhase, /* VCO phase */ COSTAS_LP_VCO_MODULATION_INDEX, /* VCO modulation index */ pCostasLpVCOLookUpTable, /* VCO look up table */ COSTAS_LP_VCO_SINE_TABLE_SIZE, /* VCO look up table size */ CARRIER_FREQUENCY / SAMPLE_RATE, /* Carrier frequency */ pCostasLpLPF1State, /* Pointer to loop filter 1 state */ &CostasLpLPF1Index, /* Pointer to loop filter 1 index */ pCostasLpLPF2State, /* Pointer to loop filter 2 state */ &CostasLpLPF2Index, /* Pointer to loop filter 2 index */ pCostasLpLPFCoeffs, /* Pointer to loop filter coefficients */ COSTAS_LP_LPF_LENGTH, /* Loop filter length */ &CostasLpLoopFilterState, /* Pointer to loop filter state */ COSTAS_LP_LOOP_FILTER_ALPHA, /* Loop filter coefficient */ FEEDBACK_MODE, /* Loop feedback mode */ &CostasLpState, /* Pointer to delayed sample */ SAMPLE_LENGTH); /* Length of input array */ #endif Display2DGraph (h2DGraph, /* Graph handle */ "Costas Loop Output", /* 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_ADD); /* New graph */ printf ("Hit 'x' to exit or to continue\n"); } while (tolower (getchar ()) != 'x'); SUF_MemoryFree (pData); /* Free memory */ SUF_MemoryFree (pCostasLpLPFCoeffs); SUF_MemoryFree (pCostasLpLPF1State); SUF_MemoryFree (pCostasLpLPF2State); SUF_MemoryFree (pCostasLpVCOLookUpTable); }