C语言写的GPS软件接收机

简介

此软件接收机采用c语言进行编写,使用GSL库,进行傅里叶分析,参考了“A Software-Defined GPS and Galileo Receiver",可以认为是GNSS_SDR的c语言版本。
测试环境为:ubuntu20.0.4

将软件接收机的输出结果,进行坐标反查,可得如下结果,可以看到位置解析正确
C语言写的GPS软件接收机_第1张图片

主要文件构成

main.c
acquisition.c
track.c
postProceeding.c

其中:acquistion.c文件实现对卫星信号的捕获工作,并将捕获结果保存在acquisitionResult结构体中,供后续的跟踪过程使用;
C语言写的GPS软件接收机_第2张图片

track.c文件实现对卫星信号的跟踪工作,并得到导航电文,跟踪结果保存在trackResult结构体中,供后续的星历计算,接收机位置结算使用;
C语言写的GPS软件接收机_第3张图片

postProceeding.c文件完成对接收机位置的计算

捕获过程

s a m p l e s P e r C o d e samplesPerCode samplesPerCode: 每一个扩频码,有多少个采样点
s e t t i n g s . s a m p l i n g F r e q   /   ( s e t t i n g s . c o d e F r e q B a s i s   /   s e t t i n g s . c o d e L e n g t h ) ) settings.samplingFreq\ /\ (settings.codeFreqBasis\ /\ settings.codeLength)) settings.samplingFreq / (settings.codeFreqBasis / settings.codeLength))
原理就是:一秒钟的所有采样点,除以一秒中的扩频码个数,得到一个扩频码中所含有的采样点数

需要使用11ms的数据进行后续的捕获操作: 其中1ms进行捕获码相位,其余10ms进行更精确的载波频率估计
关于利用fft来计算相关运算原理:
对于N点的 x [ n ] x\left[n\right] x[n],以及 h [ n ] h\left[n\right] h[n],对其进行相关运算可得:
y [ n ] = ∑ i = 0 N − 1 x [ i ] h ∗ [ i − n ] y\left[n\right] = \sum_{i=0}^{N-1}{x\left[i\right]h^\ast\left[i-n\right]} y[n]=i=0N1x[i]h[in]

而对于离散序列的卷积运算:
y [ n ] = ∑ i = 0 N − 1 x [ i ] h [ n − i ] y\left[n\right]= \sum_{i=0}^{N-1}x\left[i\right]h\left[n-i\right] y[n]=i=0N1x[i]h[ni]
其对应的傅里叶变换为:
x ( j ω ) × h ( j ω ) x(j\omega)\times h(j\omega) x()×h()
如果将 x [ n ] x\left[n\right] x[n] h ∗ [ − n ] h^\ast\left[-n\right] h[n]进行卷积运算:
y [ n ] = ∑ i = 0 N − 1 x [ i ] h ∗ [ − ( n − i ) ] y\left[n\right]=\sum_{i=0}^{N-1}{x\left[i\right]h^\ast\left[-\left(n-i\right)\right]} y[n]=i=0N1x[i]h[(ni)]
可以看到其结果是和相关运算的结果相同的。
而其对应的傅里叶变换为:
x ( j ω ) × h ∗ ( j ω ) x(j\omega)\times h^\ast\left(j\omega\right) x()×h()
则对于两个信号的相关运算,可以将其转变为傅里叶变换进行求解

        // 1. Read 2ms Data From the signal File
        int8_t *v1 = (int8_t*)malloc(sizeof(int8_t)*sampleNumbersPerCode);
        int8_t *v2 = (int8_t*)malloc(sizeof(int8_t)*sampleNumbersPerCode);
        // 11ms data to estimate the fined frequency
        int8_t *fineFreqDat = (int8_t*)malloc(sizeof(int8_t)*sampleNumbersPerCode*11);

        fread(v1, sizeof(int8_t), sampleNumbersPerCode, fid);
        fread(v2, sizeof(int8_t), sampleNumbersPerCode, fid);
        fseek(fid, 0, SEEK_SET);
        fread(fineFreqDat, sizeof(int8_t), sampleNumbersPerCode*11, fid);

        // 2. Get prn code
        double* codeData = (double*)malloc(sizeof(double)*sampleNumbersPerCode*2);
        int8_t*  caCodeSampling = (int8_t*)malloc(sizeof(int8_t)*sampleNumbersPerCode);
        for (uint32_t i=0; i<(receiverSetting->acqStatelliteList)->size; i++) {
            caCodeAfterSampling(receiverSetting, sampleNumbersPerCode, caCodeSampling, receiverSetting->acqStatelliteList->data[i]);

            // pack int8_t to gsl_vector_complex
            for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
		    REAL(codeData,i) = *(caCodeSampling+i);
		    IMAG(codeData,i) = 0;
            }

            // calculate the fft of C/A code
            gsl_fft_complex_wavetable* waveTable;
            gsl_fft_complex_workspace* workSpace;

            waveTable = gsl_fft_complex_wavetable_alloc(sampleNumbersPerCode);
            workSpace = gsl_fft_complex_workspace_alloc(sampleNumbersPerCode);

            gsl_fft_complex_forward(codeData, 1, sampleNumbersPerCode, waveTable, workSpace);

            // conjugat the code fft result
            for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
                IMAG(codeData,i) = -IMAG(codeData,i);
            }

            // check every possible frequency bin, step is 0.5Khz
            double * sinData = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            double * cosData = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            double * i_data_base_1 = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            double * q_data_base_1 = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            double * complex_data_base_1 = (double*)malloc(sizeof(double)*2*sampleNumbersPerCode);
            double * i_data_base_2 = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            double * q_data_base_2 = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            double * complex_data_base_2 = (double*)malloc(sizeof(double)*2*sampleNumbersPerCode);
            double * multiplexed_fft_result_1 = (double*)malloc(sizeof(double)*2*sampleNumbersPerCode);
            double * multiplexed_fft_result_2 = (double*)malloc(sizeof(double)*2*sampleNumbersPerCode);

            double phasePerSamplePoint = 2*M_PI/receiverSetting->samplingFreq;
            double **twoDimResult = (double**)malloc(sizeof(double*)*receiverSetting->acqSearchBand*2);

            // store the acquisition result
            for (int i=0; i<receiverSetting->acqSearchBand*2; i++) {
                twoDimResult[i] = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
            }

            for (int i=0; i<receiverSetting->acqSearchBand*2; i++) {
                // frequency for now
                double freqBin = receiverSetting->intermediatFreq - receiverSetting->acqSearchBand/2*1E3 + i*0.5*1E3;
                // local oscillator
                for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
                    sinData[i] = sin(i*freqBin*phasePerSamplePoint);
                    cosData[i] = cos(i*freqBin*phasePerSamplePoint);
                }
                // downconversion to baseband
                for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
                    i_data_base_1[i] = sinData[i] * v1[i];
                    q_data_base_1[i] = cosData[i] * v1[i];
                    REAL(complex_data_base_1, i) = i_data_base_1[i];
                    IMAG(complex_data_base_1, i) = q_data_base_1[i];

                    i_data_base_2[i] = sinData[i] * v2[i];
                    q_data_base_2[i] = cosData[i] * v2[i];
                    REAL(complex_data_base_2, i) = i_data_base_2[i];
                    IMAG(complex_data_base_2, i) = q_data_base_2[i];
                } 

                
                // Calculate the fft of the baseband signal
                gsl_fft_complex_forward(complex_data_base_1, 1, sampleNumbersPerCode, waveTable, workSpace);
                gsl_fft_complex_forward(complex_data_base_2, 1, sampleNumbersPerCode, waveTable, workSpace);

                // execute the multiplication of fft result
                for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
                    REAL(multiplexed_fft_result_1, i) = REAL(codeData, i)*REAL(complex_data_base_1, i) - IMAG(codeData, i)*IMAG(complex_data_base_1, i);
                    IMAG(multiplexed_fft_result_1, i) = REAL(codeData, i)*IMAG(complex_data_base_1, i) + IMAG(codeData, i)*REAL(complex_data_base_1, i);
                    REAL(multiplexed_fft_result_2, i) = REAL(codeData, i)*REAL(complex_data_base_2, i) - IMAG(codeData, i)*IMAG(complex_data_base_2, i);
                    IMAG(multiplexed_fft_result_2, i) = REAL(codeData, i)*IMAG(complex_data_base_2, i) + IMAG(codeData, i)*REAL(complex_data_base_2, i);
                }


                // invert the fft result to get the corelation 
                gsl_fft_complex_backward(multiplexed_fft_result_1, 1, sampleNumbersPerCode, waveTable, workSpace);
                gsl_fft_complex_backward(multiplexed_fft_result_2, 1, sampleNumbersPerCode, waveTable, workSpace);

                // gsl's invert fft is portional to ture fft result
                for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
                    REAL(multiplexed_fft_result_1, i) = REAL(multiplexed_fft_result_1, i)/sampleNumbersPerCode;
                    IMAG(multiplexed_fft_result_1, i) = IMAG(multiplexed_fft_result_1, i)/sampleNumbersPerCode;
                    REAL(multiplexed_fft_result_2, i) = REAL(multiplexed_fft_result_2, i)/sampleNumbersPerCode;
                    IMAG(multiplexed_fft_result_2, i) = IMAG(multiplexed_fft_result_2, i)/sampleNumbersPerCode;
                }

                // find the max power bwtween multiplexed_fft_reslt_1 and multiplexed_fft_result2
                double *abs_correlation_value_1, *abs_correlation_value_2;
                double abs_correlation_value_max_1, abs_correlation_value_max_2;
                abs_correlation_value_max_1 = abs_correlation_value_max_2 = 0;
                abs_correlation_value_1 = (double*)malloc(sizeof(double)*sampleNumbersPerCode);
                abs_correlation_value_2 = (double*)malloc(sizeof(double)*sampleNumbersPerCode);

                for (uint32_t i=0; i<sampleNumbersPerCode; i++) {
                    abs_correlation_value_1[i] = REAL(multiplexed_fft_result_1, i)*REAL(multiplexed_fft_result_1, i)+IMAG(multiplexed_fft_result_1, i)*IMAG(multiplexed_fft_result_1, i);
                    abs_correlation_value_max_1 = abs_correlation_value_max_1 >= abs_correlation_value_1[i] ? abs_correlation_value_max_1 : abs_correlation_value_1[i];
                    abs_correlation_value_2[i] = REAL(multiplexed_fft_result_2, i)*REAL(multiplexed_fft_result_2, i)+IMAG(multiplexed_fft_result_2, i)*IMAG(multiplexed_fft_result_2, i);
                    abs_correlation_value_max_2 = abs_correlation_value_max_2 >= abs_correlation_value_2[i] ? abs_correlation_value_max_2 : abs_correlation_value_2[i];
                }


                if (abs_correlation_value_max_1>abs_correlation_value_max_2) {
                    memcpy(twoDimResult[i], abs_correlation_value_1, sizeof(double)*sampleNumbersPerCode);
                } else {
                    memcpy(twoDimResult[i], abs_correlation_value_2, sizeof(double)*sampleNumbersPerCode);
                }
                free(abs_correlation_value_1);
                free(abs_correlation_value_2);

            }

            // Free space
            gsl_fft_complex_wavetable_free(waveTable);
            gsl_fft_complex_workspace_free(workSpace);

            // find the max point in the 2D plan
            double max = 0;
            struct acquisitionPoint acq;
            for (int i=0; i<receiverSetting->acqSearchBand*2; i++) {
                for (uint32_t j=0; j<sampleNumbersPerCode; j++) {
                    double temp = twoDimResult[i][j]; 
                    if (max<temp) {
                        max = temp;
                        acq.freqBin = i;
                        acq.codePhase = j;            
                        acq.value = max;
                    }
                }
            }

            // find the second max point in the 2D plan
            uint32_t freqBin;
            freqBin = acq.freqBin;

            double secondMax = 0;
            uint32_t startPoint, endPoint;
            startPoint = endPoint = 0;
            if (acq.codePhase <= sampleNumbersPerChip) {
                startPoint = acq.codePhase + sampleNumbersPerChip;
                endPoint = sampleNumbersPerCode - (sampleNumbersPerChip - acq.codePhase);
                for (uint32_t i=startPoint; i<endPoint; i++) {
                    if (secondMax<twoDimResult[freqBin][i]) {
                        secondMax = twoDimResult[freqBin][i];
                    }
                }
            } else if (acq.codePhase+sampleNumbersPerChip >= sampleNumbersPerCode) {
                startPoint = acq.codePhase+sampleNumbersPerChip - sampleNumbersPerCode;
                endPoint = acq.codePhase-sampleNumbersPerChip;
                for (uint32_t i=startPoint; i<endPoint; i++) {
                    if (secondMax<twoDimResult[freqBin][i]) {
                        secondMax = twoDimResult[freqBin][i];
                    }
                }
            } else {
                for (uint32_t i=0; i<acq.codePhase-sampleNumbersPerChip; i++) {
                    if (secondMax<twoDimResult[freqBin][i]) {
                        secondMax = twoDimResult[freqBin][i];
                    }
                }
                for (uint32_t i=acq.codePhase+sampleNumbersPerChip; i<sampleNumbersPerCode; i++) {
                    if (secondMax<twoDimResult[freqBin][i]) {
                        secondMax = twoDimResult[freqBin][i];
                    }
                }
            }

            if (max/secondMax >= receiverSetting->acqThreshold) {
                printf("satellite %d is Acqitioned\n", i);
                // fine the frequency
                double meanValue, sum;
                sum = meanValue = 0;
                for (uint32_t i=0; i<sampleNumbersPerCode*11; i++) {
                    sum += fineFreqDat[i];
                }
                meanValue = sum/sampleNumbersPerCode/11;

                uint32_t totalNumberForFFT = next2pow(sampleNumbersPerCode*10)*8;
                double * paddingDataFFT = (double*)malloc(sizeof(double)*totalNumberForFFT*2);
                double * absFFTValue = (double*)malloc(sizeof(double)*totalNumberForFFT);
                int8_t * caCodeSamplingFor10MS = (int8_t*)malloc(sizeof(int8_t)*sampleNumbersPerCode*10);
                // generate long CACode
                caCodeAfterSampling(receiverSetting, sampleNumbersPerCode*10, caCodeSamplingFor10MS, receiverSetting->acqStatelliteList->data[i]);

                memset(paddingDataFFT, 0, sizeof(double)*totalNumberForFFT*2);
                for(uint32_t i=0; i<sampleNumbersPerCode*10; i++) {
                    REAL(paddingDataFFT, i) = (fineFreqDat[i+acq.codePhase]-meanValue)*caCodeSamplingFor10MS[i];
                }


                //FILE *fid_temp = fopen("paddingDataFFT.dat", "w");
                //fwrite(paddingDataFFT, sizeof(double), totalNumberForFFT*2, fid_temp);
                //fclose(fid_temp);

                gsl_fft_complex_wavetable* fineWaveTable = gsl_fft_complex_wavetable_alloc(totalNumberForFFT);
                gsl_fft_complex_workspace* fineWorkSpace = gsl_fft_complex_workspace_alloc(totalNumberForFFT);

                gsl_fft_complex_forward(paddingDataFFT, 1, totalNumberForFFT, fineWaveTable, fineWorkSpace);

                for (uint32_t i=0; i<totalNumberForFFT; i++) {
                    absFFTValue[i] = sqrt(REAL(paddingDataFFT, i)*REAL(paddingDataFFT, i) + IMAG(paddingDataFFT, i)*IMAG(paddingDataFFT, i));
                }
                free(paddingDataFFT);
                gsl_fft_complex_wavetable_free(fineWaveTable);
                gsl_fft_complex_workspace_free(fineWorkSpace);

                uint32_t uniqueFreq = ceil((totalNumberForFFT+1.0)/2);

                struct finedFreq finedFreqStructure;
                finedFreqStructure.findFreqBin = 0;
                finedFreqStructure.value  = 0;
                for (uint32_t i=5; i<uniqueFreq-5; i++) {
                    if (finedFreqStructure.value<absFFTValue[i]) {
                        finedFreqStructure.value = absFFTValue[i];
                        finedFreqStructure.findFreqBin = i;
                    }
                }
                acqResult[i].flag = 1;
                acqResult[i].codePhase = acq.codePhase;
                acqResult[i].freq = receiverSetting->samplingFreq/totalNumberForFFT*(finedFreqStructure.findFreqBin+1);

                free(absFFTValue);
                free(caCodeSamplingFor10MS);
		for (int i=0; i<receiverSetting->acqSearchBand*2; i++) {
			free(twoDimResult[i]);
		}
                free(twoDimResult);
            } else {
                printf("satellite %d isnot Acqitioned\n", i);
            }
	    free(complex_data_base_1);
	    free(complex_data_base_2);
            free(i_data_base_1);
            free(q_data_base_1);
            free(i_data_base_2);
            free(q_data_base_2);
            free(sinData);
            free(cosData);
            free(multiplexed_fft_result_1);
            free(multiplexed_fft_result_2);

          }  
	    free(v1);
	    free(v2);
	    free(codeData);
	    free(caCodeSampling);
	    free(fineFreqDat);
        }

跟踪过程

无论是 D L L DLL DLL还是 P L L PLL PLL,都可以当作为一个二阶的系统
其传递函数为:
F ( s ) = 1 s × τ 2 s + 1 τ 1 F\left(s\right)=\frac{1}{s}\times\frac{\tau_2s+1}{\tau_1} F(s)=s1×τ1τ2s+1
对其进行反变换可以得到:
f ( t ) = τ 2 τ 1 σ ( t ) + 1 τ 1 u ( t ) f\left(t\right)=\frac{\tau_2}{\tau_1}\sigma\left(t\right)+\frac{1}{\tau_1}u\left(t\right) f(t)=τ1τ2σ(t)+τ11u(t)
可知当得到的误差信号经过环路滤波器的时候,发生的是卷积操作,即:
c o n ( e r r ( t ) , f ( t ) ) con\left(err\left(t\right),f\left(t\right)\right) con(err(t),f(t))
于是可得,调节NCO的量为:
τ 2 τ 1 e r r ( t ) + 1 τ 1 ∫ 0 t e r r ( τ ) d τ \frac{\tau_2}{\tau_1}err\left(t\right)+\frac{1}{\tau_1}\int_{0}^{t}err\left(\tau\right)d\tau τ1τ2err(t)+τ110terr(τ)dτ
采用的积分时间为1ms,每1ms计算一次误差值err
c a r r N c o = o l d C a r r N c o + ( t a u 2 c a r r / t a u 1 c a r r ) ∗ ( c a r r E r r o r − o l d C a r r E r r o r ) + c a r r E r r o r ∗ ( P D I c a r r / t a u 1 c a r r ) carrNco=oldCarrNco+\left(tau2carr/tau1carr\right)\ast\left(carrError-oldCarrError\right)+carrError\ast\left(PDIcarr/tau1carr\right) carrNco=oldCarrNco+(tau2carr/tau1carr)(carrErroroldCarrError)+carrError(PDIcarr/tau1carr)

          double codePhaseStep = codeFreq/samplingFreq;
                //Make sure that the last sample is the first point in the next bit
                uint32_t blksize = ceil((receiverSetting->codeLength-remCodePhase)/codePhaseStep);
                //Here need deal more carefully ***************************************************************************
                int8_t *rawSignal = (int8_t*)malloc(sizeof(int8_t)*blksize);
                //Read data from signal file
                size_t sampleRead = fread(rawSignal, sizeof(int8_t), blksize, fid);
                if(sampleRead != blksize) {
                    printf("Not able to read the specified number of samples for tracking, exiting!\n");
                    fclose(fid);
                    exit(-1);
                }

                //generate E P L code
                CACode(receiverSetting->acqStatelliteList->data[i], caCodeStandard);
                int8_t * earlyCode  = (int8_t*)malloc(sizeof(int8_t)*blksize);
                int8_t * promptCode = (int8_t*)malloc(sizeof(int8_t)*blksize);
                int8_t * lateCode   = (int8_t*)malloc(sizeof(int8_t)*blksize);

                for(uint32_t i=0; i<blksize; i++) {
                    int32_t index = codePhaseStep*i+remCodePhase;
                    // Prompt code
                    promptCode[i] = caCodeStandard[index%receiverSetting->codeLength];
                    // Early code
                    index = floor(codePhaseStep*i+remCodePhase-earlyLateSpc);
                    if (index<0) 
                        index = 1022;
                    earlyCode[i] = caCodeStandard[index%receiverSetting->codeLength];
                    // Late Code
                    index = floor(codePhaseStep*i+remCodePhase+earlyLateSpc);
                    lateCode[i] = caCodeStandard[index%receiverSetting->codeLength];
                }
                remCodePhase = codePhaseStep*(blksize)+remCodePhase - receiverSetting->codeLength;

                // Generate the carrier frequency to mix the signal to baseband
                double * carrCos, * carrSin;
                carrCos = (double*)malloc(sizeof(double)*blksize);
                carrSin = (double*)malloc(sizeof(double)*blksize);

                for(uint32_t i=0; i<blksize; i++) {
                    carrCos[i] = cos(2*M_PI*carrFreq/samplingFreq*i + remCarrPhase);
                    carrSin[i] = sin(2*M_PI*carrFreq/samplingFreq*i + remCarrPhase);
                }
                remCarrPhase = remainder(remCarrPhase+(blksize)*2*M_PI*carrFreq/samplingFreq, 2*M_PI);

                double* qBasebandSignal, *iBasebandSignal;
                qBasebandSignal = (double*)malloc(sizeof(double)*blksize);
                iBasebandSignal = (double*)malloc(sizeof(double)*blksize);

                // Not be necessary
                for (uint32_t i=0; i<blksize; i++) {
                    iBasebandSignal[i] = carrSin[i]*rawSignal[i];
                    qBasebandSignal[i] = carrCos[i]*rawSignal[i];
                }

                double I_E, Q_E, I_P, Q_P, I_L, Q_L;
                I_E = Q_E = I_P = Q_P = I_L = Q_L = 0;
                for (uint32_t i=0; i<blksize; i++) {
                    I_E = I_E + iBasebandSignal[i]*earlyCode[i];
                    Q_E = Q_E + qBasebandSignal[i]*earlyCode[i];

                    I_P = I_P + iBasebandSignal[i]*promptCode[i];
                    Q_P = Q_P + qBasebandSignal[i]*promptCode[i];

                    I_L = I_L + iBasebandSignal[i]*lateCode[i];
                    Q_L = Q_L + qBasebandSignal[i]*lateCode[i];
                }

                // Find PLL error and update carrier NCO
                double carrError = atan(Q_P/I_P) / (2*M_PI);

                double carrNco = oldCarrNco + (tau2carr/tau1carr) * (carrError-oldCarrError) + carrError *(PDIcarr/tau1carr);
                oldCarrNco = carrNco;
                oldCarrError = carrError;
                
                //upated carrier freq
                carrFreq = carrFreqBasis + carrNco;
                (*trackResults)[i].carrFreq[j] = carrFreq;


                //Find DLL error and update code NCO
                double codeError = (sqrt(I_E*I_E+Q_E*Q_E)-sqrt(I_L*I_L+Q_L*Q_L)) / (sqrt(I_E*I_E+Q_E*Q_E)+sqrt(I_L*I_L+Q_L*Q_L));
                double codeNco = oldCodeNco +(tau2code/tau1code)*(codeError-oldCodeError) + codeError *(PDIcode/tau1code);
                oldCodeNco = codeNco;
                oldCodeError = codeError;


                //updated code freq
                codeFreq = receiverSetting->codeFreqBasis - codeNco;
                (*trackResults)[i].codeFreq[j] = codeFreq;


                //store information
                (*trackResults)[i].absoluteSamples[j] = ftell(fid);
                (*trackResults)[i].dllDiscr[j] = codeError;
                (*trackResults)[i].dllDiscrFilt[j] = codeNco;
                (*trackResults)[i].pllDiscr[j] = carrError;
                (*trackResults)[i].pllDiscrFilt[j] = carrNco;
                (*trackResults)[i].I_E[j] = I_E;
                (*trackResults)[i].Q_E[j] = Q_E;
                (*trackResults)[i].I_P[j] = I_P;
                (*trackResults)[i].Q_P[j] = Q_P;
                (*trackResults)[i].I_L[j] = I_L;
                (*trackResults)[i].Q_L[j] = Q_L;


                // freee space
                free(rawSignal);
                free(earlyCode);
                free(promptCode);
                free(lateCode);
                free(carrCos);
                free(carrSin);
                free(iBasebandSignal);
                free(qBasebandSignal);

后续有时间的话,我会再将捕获和跟踪部分,做更加详细的说明,同时欢迎各位有能力和意愿的同学和我一块把这个接收机做的更加完善。
软件接收机地址

你可能感兴趣的:(c语言,开发语言)