diff --git a/core/c_functions/channel_l1ca.c b/core/c_functions/channel_l1ca.c index 8498a6a..f1f9902 100644 --- a/core/c_functions/channel_l1ca.c +++ b/core/c_functions/channel_l1ca.c @@ -2,8 +2,17 @@ #include #include +/// CONSTANTS // GPS' definition of Pi #define PI 3.1415926535898 +#define GPS_L1CA_CODE_SIZE_BITS 1023 +#define GPS_L1CA_CODE_FREQ 1.023e6 +#define IDX_I_EARLY 0 +#define IDX_Q_EARLY 1 +#define IDX_I_PROMPT 2 +#define IDX_Q_PROMPT 3 +#define IDX_I_LATE 4 +#define IDX_Q_LATE 5 // ==================================================================================================================== typedef enum { @@ -17,15 +26,63 @@ typedef enum { typedef struct st_Channel_L1CA st_Channel_L1CA; struct st_Channel_L1CA { + // Channel + int channelID; ChannelState channelState; + + // RF Signal + size_t size; + complex double* rfData; + float samplingFrequency; + + // Satellite variables + int satelliteID; // PRN number + int* code; // PRN code sequence (size 1023 for GPS L1CA) + + // Numerically Controled Oscilator (NCO) + double NCO_code; + double NCO_codeError; + double NCO_remainingCode; + double NCO_carrier; + double NCO_carrierError; + double NCO_remainingCarrier; + + // Current signal + double initialCarrierFreq; + double codeStep; + double codeCounter; + + // Acquisition parameters + + + // Tracking parameters + double* correlatorsSpacing; + double track_dll_tau1; + double track_dll_tau2; + double track_dll_pdi; + double track_pll_tau1; + double track_pll_tau2; + double track_pll_pdi; + double track_requiredSamples; }; // -------------------------------------------------------------------------------------------------------------------- -void ProcessHandler(st_Channel_L1CA channel){ +void run_ChannelL1CA(st_Channel_L1CA channelVar){ - switch (channel.channelState) + // Process new RF data + ProcessHandler(channelVar); + + return; +} + + +// -------------------------------------------------------------------------------------------------------------------- + +void ProcessHandler(st_Channel_L1CA channelVar){ + + switch (channelVar.channelState) { case IDLE: // Nothing to do @@ -36,7 +93,7 @@ void ProcessHandler(st_Channel_L1CA channel){ break; case TRACKING: - RunTracking(); + RunTracking(channelVar); RunDecoding(); break; @@ -44,6 +101,7 @@ void ProcessHandler(st_Channel_L1CA channel){ break; } + return; } // -------------------------------------------------------------------------------------------------------------------- @@ -54,8 +112,48 @@ void RunAcquisition(){ // -------------------------------------------------------------------------------------------------------------------- -void RunTracking(){ +void RunTracking(st_Channel_L1CA channelVar){ + + double correlatorsResults[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + // Compute correlators, Early-Prompt-Late (EPL) implementation + double carrierFrequency = channelVar.initialCarrierFreq + channelVar.NCO_carrier; + EPL( + channelVar.rfData, channelVar.code, channelVar.size, carrierFrequency, channelVar.samplingFrequency, + channelVar.NCO_remainingCarrier, channelVar.NCO_remainingCode, channelVar.codeStep, + channelVar.correlatorsSpacing, correlatorsResults + ); + + // Delay Lock Loop (DLL) operations + DLL_NNEML( + correlatorsResults[IDX_I_EARLY], correlatorsResults[IDX_Q_EARLY], + correlatorsResults[IDX_I_LATE], correlatorsResults[IDX_Q_LATE], + channelVar.track_dll_tau1, channelVar.track_dll_tau2, channelVar.track_dll_pdi, + channelVar.NCO_code, channelVar.NCO_codeError + ); + + // Phase Lock Loop (PLL) operations + PLL_costa( + correlatorsResults[IDX_I_PROMPT], correlatorsResults[IDX_Q_PROMPT], + channelVar.track_pll_tau1, channelVar.track_pll_tau2, channelVar.track_pll_pdi, + channelVar.NCO_carrier, channelVar.NCO_carrierError + ); + + // Updates variables + double codeFrequency = GPS_L1CA_CODE_FREQ - channelVar.NCO_code; + double carrierFrequency = channelVar.initialCarrierFreq + channelVar.NCO_carrier; + + channelVar.codeCounter += 1; + channelVar.codeStep = codeFrequency / channelVar.samplingFrequency; + + // Update NCO + channelVar.NCO_remainingCode += channelVar.track_requiredSamples * channelVar.codeStep - GPS_L1CA_CODE_SIZE_BITS; + channelVar.NCO_remainingCarrier -= carrierFrequency * 2.0 * PI * channelVar.track_requiredSamples / channelVar.samplingFrequency; + channelVar.NCO_remainingCarrier = fmod(channelVar.NCO_remainingCarrier, 2.0*PI); + + channelVar.track_requiredSamples = ceil((GPS_L1CA_CODE_SIZE_BITS - channelVar.NCO_remainingCode) / channelVar.codeStep); + return; } @@ -97,6 +195,42 @@ void EPL(complex double* rfData, double* code, size_t size, double carrierFreque return; } +// -------------------------------------------------------------------------------------------------------------------- + +void DLL_NNEML(double iEarly, double qEarly, double iLate, double qLate, double tau1, double tau2, double pdi, + double r_NCO_code, double r_NCO_codeError){ + + // Compute new code error + double earlySqrt = sqrt(iEarly*iEarly + qEarly*qEarly); + double lateSqrt = sqrt(iLate*iLate + qLate*qLate); + double newCodeError = (earlySqrt - lateSqrt) / (earlySqrt + lateSqrt); + + // Update NCO accordingly + r_NCO_code += tau2 / tau1 * (newCodeError - r_NCO_codeError); + r_NCO_code += pdi / tau1 * newCodeError; + + r_NCO_codeError = newCodeError; + + return; +} + +// -------------------------------------------------------------------------------------------------------------------- + +void PLL_costa(double iPrompt, double qPrompt, double tau1, double tau2, double pdi, + double r_NCO_carrier, double r_NCO_carrierError){ + + // Compute new carrier error + double newCarrierError = atan(qPrompt / iPrompt) / 2.0 / PI; + + // Update NCO accordingly + r_NCO_carrier += tau2 / tau1 * (newCarrierError - r_NCO_carrierError); + r_NCO_carrier += pdi / tau1 * newCarrierError; + + r_NCO_carrierError = newCarrierError; + + return; +} + // ====================================================================================================================