Main Content

This example shows how to generate Global Positioning System (GPS) legacy navigation (LNAV) data, its frame structure, and the complex baseband waveform. The spreading of the data is performed with coarse acquisition code (C/A-code) and precision code (P-code). To design a navigation system based on GPS, testing the receiver with a received signal is required. The signal received from a satellite is not useful for this purpose, as transmitter and channel parameters cannot be controlled. To test the receiver, a waveform generated under a controlled set of parameters is required.

Obtain the GPS data bits, which are transmitted at a rate of 50 bits per second (bps). Apply C/A-code spreading on the generated data. This C/A-code has a rate of 1.023 mega chips per second. Because one data bit is transmitted for every 0.02 seconds (50 bps), each data bit is spread with 0.02*1.023*1e6 = 20460 chips. The data is also spread with the P-code. This P-code has a rate of 10.23 mega chips per second which implies that each data bit is spread with 204600 chips of P-code.

GPS data contains various configuration parameters, clock parameters, and parameters related to the location of a satellite vehicle (SV) in space. All of these parameters can be classified into three broad categories:

Ephemeris parameters

Almanac parameters

Parameters that are neither ephemeris nor almanac, which include configuration parameters, clock parameters, ionosphere parameters, Universal Time Coordinated (UTC) parameters, and navigation message correction tables (NMCT) parameters

GPS satellites transmit signals on two frequencies: L1 (1575.42 MHz) and L2 (1227.60 MHz). Both signals are generated from a base frequency of 10.23 MHz. The signal frequency of L1 is 154*10.23 MHz = 1575.42 MHz, and the signal frequency of L2 is 120*10.23 MHz = 1227.60 MHz. Legacy GPS satellites transmit different spreading codes and data on L1 and L2 carrier frequencies. For details, see IS-GPS-200L Table 3-III [1].

Three kinds of spreading for legacy GPS exist:

C/A-code spreading

P-code spreading

Y-code spreading

Y-code is not available for public use. Because Y-code is an encrypted version of P-code, P-code and Y-code are used together as P(Y)-code.

On the L1 carrier frequency, the in-phase component carries P(Y)-code along with data.

On the L1 carrier frequency, the quadrature-phase component carries C/A-code along with data.

On the L2 carrier frequency, the in-phase component contains either P(Y)-code with data, P(Y)-code without data, or C/A-code with data.

On the L2 carrier frequency, the quadrature-phase component is empty.

This example demonstrates the signal on the L1 carrier frequency, which contains P-code on the in-phase component and C/A-code on the quadrature-phase component.

GPS satellites transmit data in 1500 bit-length frames with each frame consisting of five subframes of 300 bits in each subframe. Because the data rate is 50 bps, transmitting each subframe takes 6 seconds and transmitting each frame takes 30 seconds. Each subframe is made up of 10 words with 30 bits in each word. The GPS data contains information regarding the clock and the position of the satellites. To enable computation of the distance from a satellite to a receiver, the navigation data is spread with two types of codes: C/A-code and P-code. C/A-code is at 1.023 MHz and repeats after 1023 chips. P-code is at 10.23 MHz and repeats after each week for a given satellite.

This figure illustrates the legacy navigation (LNAV) data frame.

Subframe 1 contains information about the type of code (C/A or P) and the presence of data on the L2 channel. Subframe 1 also provides the clock information on-board a satellite.

Subframes 2 and 3 contain information about the position of the transmitting SV in space through orbital information of the satellite. This orbital information of the SV is called ephemeris.

Subframes 4 and 5 contain information about the position of the GPS satellites that are currently operating and gives an estimate of satellites that are visible to a user. This information about positions of all satellites in the constellation is collectively called almanac. Ephemeris gives the accurate position of the SV in space, and almanac contains less accurate position information of all the SVs. Almanac data of the SVs is spanned over 25 frames. Because transmitting each frame takes 30 seconds, transmitting the entire almanac spanned over 25 frames takes 12.5 minutes.

Select the `ShowVisualizations`

parameter to enable the spectrum and correlation plot visualizations. Select the `WriteWaveformToFile`

parameter to write the complex baseband waveform to a file if needed.

ShowVisualizations = true; WriteWaveformToFile = false;

Specify the satellite pseudo-random noise (PRN) index.

PRNIndex = 1;

Because generating the GPS waveform for the entire navigation data takes a lot of time and memory, this example demonstrates generating waveform for one bit of the navigation data. Generating the waveform for number of GPS LNAV data bits can be controlled by the parameters `NavDataBitStartIndex`

and `NavDataBitEndIndex`

.

NavDataBitStartIndex = 1321; % Set this value to 1 to generate waveform from the first bit of navigation data NavDataBitEndIndex = 1321; % Set this value to navigation data length to generate waveform till the last bit

Specify for frames for which legacy GPS waveform should be generated.

`FrameIndices = 1:25; % This value must be consecutive integers in the range [1, 25]`

GPS data generation involves initializing the relevant parameters. This section shows how to initialize these parameters.

```
svparams.PRNIdx = PRNIndex; % Current satellite PRN index
svparams.FrameIndices = FrameIndices;
```

In each subframe, Word 1 is the TLM word, and word 2 is the HOW. As shown in this figure, the TLM word contains an eight-bit preamble, the TLM message, integrity status flag, and parity. The last 6 bits of each word contains parity. These parity bits are calculated based on the algorithm presented in IS-GPS-200L Table 20-XIV [1].

svparams.TLMPreamble = 139; % Decimal equivalent of [1 0 0 0 1 0 1 1] svparams.TLMMessage = 0; % Contains information needed by the precise positioning service (PPS) user that is authorized user svparams.TLMIntegrityStatusFlag = 0; % Legacy level of integrity

The next figure shows the fields in the HOW. The first 17 bits of the HOW indicate the 17 most significant bits (MSBs) of the time of week (TOW). The TOW is a 19-bit number, and the least significant bit (LSB) of the TOW ticks for every 1.5 seconds. The TOW in the HOW (which is the 17 MSBs of the full TOW) ticks for every 6 seconds. That is, the TOW in the HOW ticks for each subframe. For example, if the TOW value is 1000 at the current instance, then after 1.5 seconds, the TOW is 1001. After another 1.5 seconds, the TOW is 1002, and so on. If the 17 MSBs of the TOW (which is in the HOW) are considered, then for every 4 ticks of full TOW, this TOW-in-HOW ticks for one time. Because each set of 4 ticks in the full TOW corresponds to 6 seconds, the TOW-in-HOW ticks for every 6 seconds.

The 18th bit in the HOW is the alert flag that indicates that the user range accuracy (URA) of the standard positioning service (SPS) user is worse than what is indicated by the `svparams.URAIndex`

, and user must use the current satellite at their own risk. Bit 19 in the HOW is the antispoof flag. If this flag is set, then in place of transmitting P-code, the satellite transmits the Y-code. Bits 20 to 22 in the HOW indicate the subframe ID. Last two bits of 6 bits parity are set to zero, and bits 23 and 24 are solved to set the last two bits of the parity to zero.

svparams.HOWTOW = 2000; % Decimal equivalent of 17 MSBs of TOW svparams.HOWAlertFlag = 0; % Alert flag svparams.AntiSpoofFlag = 0; % Antispoof flag svparams.SubframeID = 1; % Subframe ID of starting subframe

In theory, clocks of all satellites must be synchronized, which implies that all GPS satellite clocks must show the same time at a given moment in time. In practice, deterministic satellite clock error characteristics of bias, drift, and aging as well as satellite implementation characteristics of group delay bias and mean differential group delay exist. These errors deviate the satellite clocks from the GPS system time. These clock parameters are transmitted in subframe 1. Along with the clock information, subframe 1 also contains various configuration information. This code initializes these parameters. For a detailed description of parameters in subframe 1, see IS-GPS-200L [1].

svparams.WeekNumberMod1024 = 39; % Week number modulo 1024 to fit in 10 bits of data. % Same as in Almanac file svparams.CodesOnL2Channel = 2; % Value of 2 indicates C/A-code on L2 channel % Value of 1 indicates P code on L2 channel svparams.DataFlagForL2P = 1; % Value of 1 indicates nav data Off on P-code % of in-phase component of L2 channel svparams.URAIdx = 0; % User range accuracy (URA) index. % Refer IS-GPS-200L Section 20.3.3.3.1.3 [1] svparams.SVHealth = 0; % SV health svparams.IODC = 0; % Issue of data, clock (IODC) svparams.T_GD = 0; % Estimated group delay differential svparams.t_oc = 0; % Clock data reference time svparams.a_f2 = 0; % Second order clock correction coefficient svparams.a_f1 = 0; % First order clock correction coefficient svparams.a_f0 = 0; % Zeroth order clock correction coefficient

Frame 13 of subframe 4 includes the NMCT range corrections. These range corrections are done using estimated range deviation (ERD) values for each satellite. The way in which NMCT values are mapped to ERD values is defined in IS-GPS-200L [1].

`svparams.NMCTAvailabilityIndicator`

is a 2-bit integer value that indicates the availability of NMCT data.

`0 -`

NMCT available for both precise positioning service (PPS) user and standard positioning service (SPS) user`1 -`

NMCT is available only to authorized users`2 -`

No correction table is available to any user`3 -`

Reserved for future use

`svparams.NMCTAvailabilityIndicator = 0; % NMCT available to both PPS and SPS users`

The code initializes the ERD values for a particular satellite. The values are initialized to zero. The valid range is from `-9.3`

to `9.3`

meters. Each array element indicates the corresponding ERD value (that is, the first element is ERD01, the second element is ERD02, and so on).

```
svparams.NMCTERD = zeros(30,1); % Units are in meters
```

A frequency dependent delay is caused due to propagation of signal through ionosphere. This delay is one of the significant errors in calculation of accurate time. To compensate for this delay due to ionosphere, dual frequency receivers need to be used for accurate positioning of the receiver. To provide a rough model of the ionosphere and delay caused by it for single frequency receivers, GPS transmits some parameters on the GPS data in subframe 4. These parameters are initialized as follows.

svparams.Ionosphere.alpha = zeros(4,1); % Units of each element in the array is seconds svparams.Ionosphere.beta = zeros(4,1); % Units of each element in the array is seconds

Subframe 4 of the GPS LNAV data contains parameters to correlate UTC with that of the GPS time. This code initializes these parameters.

svparams.UTC.A_1 = 0; % In seconds/second svparams.UTC.A_0 = 0; % In seconds svparams.UTC.t_ot = 0; % In seconds svparams.UTC.WN_t = 39; % In weeks. Same value as in almanac file svparams.UTC.WN_LSF = 39; % In weeks. Same value as in almanac file svparams.UTC.Delt_LS = 0; % In seconds svparams.UTC.DN = 0; % In days svparams.UTC.Delt_LSF = 0 % In seconds

`svparams = `*struct with fields:*
PRNIdx: 1
FrameIndices: [1x25 double]
TLMPreamble: 139
TLMMessage: 0
TLMIntegrityStatusFlag: 0
HOWTOW: 2000
HOWAlertFlag: 0
AntiSpoofFlag: 0
SubframeID: 1
WeekNumberMod1024: 39
CodesOnL2Channel: 2
DataFlagForL2P: 1
URAIdx: 0
SVHealth: 0
IODC: 0
T_GD: 0
t_oc: 0
a_f2: 0
a_f1: 0
a_f0: 0
NMCTAvailabilityIndicator: 0
NMCTERD: [30x1 double]
Ionosphere: [1x1 struct]
UTC: [1x1 struct]

Display the structure `svparams.Ionosphere.`

disp(svparams.Ionosphere)

alpha: [4x1 double] beta: [4x1 double]

Display the structure `svparams.UTC.`

disp(svparams.UTC)

A_1: 0 A_0: 0 t_ot: 0 WN_t: 39 WN_LSF: 39 Delt_LS: 0 DN: 0 Delt_LSF: 0

GPS satellites revolve around the Earth in an elliptical orbit, with Earth at one of the focal points of the ellipse. A set of orbital parameters that accurately defines a satellite position in this elliptical orbit is called *ephemeris*. Each GPS satellite transmits its own ephemeris data on subframes 2 and 3. This figure shows three orbital parameters for a satellite in the Earth-centered Earth fixed (ECEF) coordinate system. This figure does not show an actual GPS satellite, and the figure is for illustration only.

Length of semimajor axis, A: Distance from the center of the elliptical orbit of the satellite to the apogee

Inclination angle: Angle between the equatorial plane of Earth and the plane of orbit of satellite

Longitude of ascending node, $\Omega $: Angle between the Greenwich meridian and the direction of the ascending node

Define a structure, called `ephemerisparams`

, that stores the ephemeris parameters. The parameters that convey angle are in the units of semicircles, because the GPS standard [1] specifies these parameters in semicircles. One semicircle is equal to $\pi $ radians (180 degrees).

ephemerisparams.SqrtA = 0; % Square root of length of semimajor axis ephemerisparams.i_0 = 0; % Inclination angle (in semicircles) ephemerisparams.Omega_0 = 0; % Longitude of ascending node at weekly epoch (in semicircles)

This next figure shows two orbital parameters:

Argument of perigee, $\omega $: Angle between the direction of the ascending node and the direction of perigee

True anomaly, $\upsilon $: Angle between the direction of the perigee and the direction in which current position of the satellite is present

Per Kepler's second law of planetary motion, the angular velocity (rate of change of true anomaly) is different at different locations in the orbit. You can define the mean anomaly, whose rate of change is constant over the entire orbit of the satellite. In GPS ephemeris parameters, rather than specifying true anomaly, mean anomaly is specified (from which true anomaly can be found). The algorithms that relate mean anomaly and true anomaly are given in IS-GPS-200L Table 20-IV [1].

The eccentricity of the ellipse also defines the orbit. Eccentricity gives a measure of deviation of the elliptical orbit from the circular shape.

ephemerisparams.omega = 0; % Argument of perigee (in semicircles) ephemerisparams.M_0 = 0; % Mean anomaly at reference time (in semicircles) ephemerisparams.e = 0; % Eccentricity of the ellipse

These ephemeris parameters aid in getting the exact location of satellite in the space.

ephemerisparams.IODE = 0; % Issue of data, ephemeris ephemerisparams.c_rs = 0; % Amplitude of the Sine Harmonic Correction Term to % the Orbit Radius (in meters) ephemerisparams.Deln = 0; % Mean Motion Difference From Computed Value (in semi-circles/second) ephemerisparams.c_uc = 0; % Amplitude of the Cosine Harmonic Correction Term to % the Argument of Latitude (in radians) ephemerisparams.c_us = 0; % Amplitude of the Sine Harmonic Correction Term to % the Argument of Latitude (in radians) ephemerisparams.t_oe = 0; % Reference time ephemeris (in seconds) ephemerisparams.FitIntervalFlag = 0; % Fit interval flag ephemerisparams.AODO = 0; % Age of data offset ephemerisparams.c_ic = 0; % Amplitude of the Cosine Harmonic Correction Term to % the Angle of Inclination (in radians) ephemerisparams.c_is = 0; % Amplitude of the Sine Harmonic Correction Term to % the Angle of Inclination (in radians) ephemerisparams.c_rc = 0; % Amplitude of the Cosine Harmonic Correction Term to % the Orbit Radius (in meters) ephemerisparams.OmegDot = 0; % Rate of Right Ascension (in semi-circles/second) ephemerisparams.IDOT = 0 % Rate of Inclination Angle (in semi-circles/secon)

`ephemerisparams = `*struct with fields:*
SqrtA: 0
i_0: 0
Omega_0: 0
omega: 0
M_0: 0
e: 0
IODE: 0
c_rs: 0
Deln: 0
c_uc: 0
c_us: 0
t_oe: 0
FitIntervalFlag: 0
AODO: 0
c_ic: 0
c_is: 0
c_rc: 0
OmegDot: 0
IDOT: 0

*Almanac* is a set of parameters that defines the position of the satellites in the orbit. In contrast with ephemeris, almanac is less precise. Additionally, ephemeris is for only one satellite, whereas almanac is for all satellites in the constellation. A receiver obtains almanac data by decoding the GPS data. A satellite continually gets this almanac data from the control segment (CS). Almanac is available to download from the navcen website. This example uses the system effective model (SEM) format of almanac data (see [2]) and extracts the almanac data as shown below.

filename = 'gpsAlmanac.txt'; % Almanac file name (this file should be in current folder) % Use any almanac file almanacparams = HelperGPSAlmanac2Struct(filename)

`almanacparams = `*struct with fields:*
SatellitesPRNIndices: [31x1 double]
WeekNumModulo1024: 39
t_oa: 589824
Data: [1x31 struct]

To generate a GPS signal at the baseband, follow these steps.

Generate the navigation data bits at 50 bits per second.

Generate the C/A-code at 1.023 mega chips per second.

Perform the XOR operation of C/A-code with the navigation data to spread the data.

BPSK-modulate the C/A-code chips by mapping bit 0 to +1 and bit 1 to -1.

Repeat above three steps for P-code at a chip rate of 10.23 mega chips per second.

Repeat each C/A-code chip 10 times to match the P-code frequency.

Place P-code and C/A-code on appropriate I and Q branches to create a complex baseband signal.

If needed, write this baseband waveform to a file for later use.

After all of the parameters for the navigation data and spreading code are initialized, generate legacy GPS navigation data using the helper function `HelperGPSLNAVData`

.

`lnavData = HelperGPSLNAVData(svparams,ephemerisparams,almanacparams); % Generates data for given FrameIndices`

Because the GPS data is at 50 bits per second, and the C/A-code is at 1.023 mega chips per second, every data bit corresponds to 20460 C/A-code chips. Because creating chips for all of the data at a single time costs a great deal of memory, C/A-code spreading is done for one LNAV data bit at a time within a loop. The PRN code rate is referred to as "chip rate" rather than "bit rate" to differentiate the notation with the data bit rate. In a navigation system, the spreading code (in this example C/A-code or P-code) is called a *ranging code* because this code is used at the receiver to calculate the propagation time of the signal. The distance from the satellite to the receiver is measured by multiplying the propagation time with the speed of light in free space.

prnCAChipRate = 1.023e6; % In chips/second gpsDataRate = 50; % In bits/second

Number of chips in one data bit is chip rate/data rate.

numCAChipsPerDataBit = prnCAChipRate/gpsDataRate

numCAChipsPerDataBit = 20460

The C/A-code is a fixed binary-valued vector for a given data bit, so generating the C/A-code for every data bit that is transmitted is not necessary. Generate the C/A-code corresponding to one navigation data bit outside the loop.

CACode = HelperGPSCACode(svparams.PRNIdx,numCAChipsPerDataBit);

Take one bit of navigation data and spread using the P-code. Take length of the P-code to match in time the C/A-code length that is already taken. Because the C/A-code is at the rate of 1.023 mega chips per second with 20,460 chips per one bit of navigation data, and P-code is at the rate of 10.23 mega chips per second, 204,600 chips of P-code exist for one bit of navigation data.

`numPChipsPerDataBit = numCAChipsPerDataBit*10 % Because chip rate of P-code is 10 times the chip rate of C/A-code`

numPChipsPerDataBit = 204600

The length of the P-code is such that it has a periodicity of 1 week. P-code chipping at the rate of 10.23 mega chips per second implies that 10.23x10^6 chips exist for every second. Because one week contains 604,800 seconds, the length of the P-code in one period is 10.23*10^6 * 604800 = 6187104000000 chips. To generate the P-code along with the length of sequence, the number of chips that are elapsed from the beginning of the week is needed, which is calculated from the `HOWTOW`

value of the first subframe and its bit index.

`numSecondsElapsed = (svparams.HOWTOW-1)*6; % Because each subframe is processed in 6 seconds`

Initialize the file into which the waveform is written.

if WriteWaveformToFile == 1 bbWriter = comm.BasebandFileWriter('Waveform.bb',10.23e6,0); end

Independently process each navigation data bit in a loop.

for iDataBit = NavDataBitStartIndex:NavDataBitEndIndex spreadedCA = xor(CACode,lnavData(iDataBit)); M = 2; % Modulation order (for BPSK, M = 2) bpskSigCA = pskmod(double(spreadedCA),M);

Due to these two reasons, the number of P-code chips that are processed just before the start of the data bit in consideration is calculated as shown in this code.

Every second, 10.23*10^6 P-code chips are processed.

Each data bit is spread with

`numPChipsPerDataBit`

number of P-code chips.

numPChipsPassed = round(numSecondsElapsed*10.23*10^6+(iDataBit-1)*numPChipsPerDataBit);

Generate the P-code.

PCode = HelperGPSPCode(numPChipsPerDataBit,svparams.PRNIdx,numPChipsPassed); spreadedWithP = xor(PCode,lnavData(iDataBit));

BPSK-modulate the P-code.

bpskSigP = pskmod(double(spreadedWithP),M);

Generate the baseband waveform of the GPS L1 signal by placing the P-code on the I-branch and C/A-code on the Q-branch. Before the baseband waveform is generated, the BPSK signal that is generated by spreading with the C/A-code is repeated 10 times (because the P-code is 10 times faster than the C/A-code). Unlike a communication link, which typically has a pulse shaping filter in the digital baseband, a GPS transmitter does not have a pulse shaping filter. For precise ranging, a satellite receiver must reproduce the spreading waveform, which can be accomplished by a rectangular pulse. Spectral efficiency of the signal is not a major concern in navigation applications.

repeatedBPSKSigCA = repelem(bpskSigCA(:),10); gpsBBWaveform = bpskSigP(:) + 1j*repeatedBPSKSigCA(:); if WriteWaveformToFile == 1 bbWriter(gpsBBWaveform); end end

Close the file if it is opened.

if WriteWaveformToFile == 1 release(bbWriter); end

Plot autocorrelation of the C/A-code and visualize the spectrum of the GPS signals.

`if ShowVisualizations`

The ranging codes designed for GPS have very good autocorrelation and crosscorrelation properties. Autocorrelation of the sequence is near-zero except at zero delay, and crosscorrelation of two different sequences is near-zero. As the C/A-code is periodic with period of 1023 bits, autocorrelation has a peak for a delay of every 1023 bits.

lags = (-1023:1023).'; plot(lags,xcorr(real(bpskSigCA(1:1023)),1023)); grid on; xlabel('Number of Samples Delayed') ylabel('Autocorrelation Value') title('Autocorrelation of GPS C/A-Code')

The spectrum plot shows the comparison of the power spectral density of signals spread with C/A-code and P-code. The plot shows that the P-code is wider.

repeatFactor = 40; % Repeat the generated BPSK signal of C/A-code to see the adjacent bands spectrum updataCA = repmat(bpskSigCA(:).',repeatFactor,1); updataCA = real(updataCA(:)); % Repeat the generated BPSK signal of P-code to see the adjacent bands spectrum updataP = repmat(bpskSigP(:).',repeatFactor/10,1); % Repeat the P-code ten times less as every chip of C/A-code correspond to 10 chips of P-code updataP = real(updataP(:)); caAndPCodeScope = dsp.SpectrumAnalyzer('SampleRate',prnCAChipRate*repeatFactor, ... 'PlotAsTwoSidedSpectrum',true, ... 'SpectrumType','Power density', ... 'AveragingMethod','Exponential', ... 'SpectrumUnits','dBW', ... 'YLimits',[-130, -50], ... 'Title','Comparison of Power Spectral Density of GPS C/A-Code and P-Code Signal', ... 'ShowLegend',true, ... 'ChannelNames',{'C/A-code spectrum','P-code spectrum'}); caAndPCodeScope([updataCA,updataP]);

Plot the signal power spectral density at the baseband. To observe the adjacent band spectrum for the GPS signal, repeat the signal at the baseband.

repeatFactor = 4; % Repeating the generated BPSK signal to see the adjacent bands spectrum updata = repmat(gpsBBWaveform(:).', repeatFactor, 1); updata = updata(:); bbscope = dsp.SpectrumAnalyzer('SampleRate',10*prnCAChipRate*repeatFactor, ... 'PlotAsTwoSidedSpectrum',true, ... 'SpectrumType','Power density', ... 'AveragingMethod','Exponential', ... 'SpectrumUnits','dBW', ... 'YLimits',[-120,-50], ... 'Title', 'Power Spectral Density of Complex Baseband GPS Signal'); bbscope(updata); end

This example uses three structures: `svparams`

, `ephemerisparams`

, and `almanacparams`

. These structures generate GPS data bits and the navigation signal in the baseband. You can also replace the parameters in each of these structures and observe how the GPS data is generated. You can change the ephemeris parameters with an existing real data set and pass those parameters into the ephemeris. Additionally, you can specify your own almanac file. If using your own almanac file, the week number in the almanac file and the week number in the `svparams`

structure must match.

Further, this example shows how to generate a GPS baseband waveform, which can be extended to generate an intermediate frequency (IF) waveform from the baseband waveform by multiplying a cosine signal on the I-branch and a sine signal on the Q-branch.

Additionally, this example shows how to generate a GPS waveform from one satellite, which can be combined along with multiple satellite PRN codes to get an integrated signal.

This example uses these data and helper files:

gpsAlmanac.txt - Almanac data file downloaded from Navcen website

HelperGPSAlmanac2Struct.m - Convert text file of almanac to structure

HelperGPSCACode.m - Generate C/A-code to spread data

HelperGPSPCode.m - Generate P-code to spread data

HelperGPSLNAVData.m - Create legacy navigation frame from data that is in structures

[1] IS-GPS-200, Rev: L; NAVSTAR GPS Space Segment/Navigation User Segment Interfaces; May 14, 2020; Code Ident: 66RP1.

[2] ICD-GPS-240, Rev: C; Navstar GPS Control Segment to User Support Community Interfaces; March 4, 2019; Code Ident: 66RP1.