Main Content

GNSS Signal Transmission Using Software-Defined Radio

Since R2024b

This example shows how to generate a global positioning system (GPS) waveform and transmit using a software-defined radio (SDR). You can use this example to employ the generated GPS waveform to test your receiver. Though this example describes the generation of a GPS waveform, you can extend it to accommodate other global navigation satellite system (GNSS) technologies.

For more details on how to generate a GPS waveform for a single satellite see the GPS Waveform Generation example.

This example follows these steps.

  1. Use a GPS almanac file to simulate the satellite constellation.

  2. Specify the receiver position to create a realistic GPS waveform scenario.

  3. Simulate the satellite environment to calculate the relative positions of satellites to the modeled receiver.

  4. Compute the Doppler shift, delay, and power of the received signal in this scenario.

  5. Generate a baseband GPS waveform using gpsWaveformGenerator System object™.

  6. Introduce impairments like Doppler shift and delay into the generated baseband signal using the results of step 4.

  7. Transmit the impaired baseband waveform through an SDR.

This figure illustrates the waveform generation process.

WaveformGeneration.png

Using this example, you can save the GPS waveform to a file or transmit the signal over-the-air using a supported SDR.

GNSSSDRWorkFlow.png

Initialize and Configure Parameters

The GPS Waveform Generation example shows waveform generation from only one satellite without any impairments. In this example, you can generate a multi-satellite waveform by simulating a satellite scenario and transmit that waveform over-the-air using an SDR.

Specify the configuration parameters to generate the waveform.

useSDR            = false;                  % In the default case, do not use SDR
WriteWaveToFile   = false;
waveformFileName  = "gpsBBWaveform.bb"; % File extension is always .bb
signalType        = "GPS C/A"; % Possible values: "GPS C/A" | "GPS L1C", "GPS L2C" | "GPS L5"
centerFrequency   = 1575.42e6; % Possible values: L1 (1575.42 MHz), L2 (1254.35 MHz), and L5 (1176.45 MHz)
sampleRate        = 5000000; % In Hz
rxlla             = [17.4349,78.3827,19]; % Receiver position in latitude (degrees), longitude (degrees), and altitude (m)
waveDuration      = 10; % Waveform duration in seconds
enableImpairments =  true;                 % Option to enable or disable impairments
minElevationAngle = 10; % In degrees. Below this elevation angle satellites are not considered in simulation
seed              = 73; % Seed for getting reproducible results
useSEMAlmanac     = "stored"; % File to derive ephemeris data and satellite simulation
if useSEMAlmanac == "stored"
    % Provide the system effectiveness model (SEM) almanac file name
    almFileName   = "gpsAlmanac.txt"; % Almanac file name
    % Provide the startTime
    startTime = datetime(2021,6,24,0,0,48,TimeZone="UTC");
else
    % Download the latest SEM almanac file from the Navigation Center
    % website and store the file
    url = "https://www.navcen.uscg.gov/sites/default/files/gps/almanac/current_sem.al3";
    currentDay = string(datetime("today",TimeZone="UTC"));
    almFileName = "gps_SEM_" + currentDay + "_UTC.txt";
    websave(almFileName,url)

    % Uses the latest SEM almanac file. Set the startTime to current date
    % and time.
    startTime = datetime("now",TimeZone="UTC");
end

Based on the specified signalType, initialize few configuration parameters.

wavegenobj = gpsWaveformGenerator(SampleRate=sampleRate);
switch(signalType)
    case "GPS C/A"
        wavegenobj.SignalType = "legacy";
        navDataType = "LNAV";
    case "GPS L1C"
        wavegenobj.SignalType = "l1C";
        navDataType = "CNAV2";
    case "GPS L2C"
        wavegenobj.SignalType = "l2C";
        navDataType = "CNAV";
    case "GPS L5"
        wavegenobj.SignalType = "l5";
        navDataType = "L5";
end
stepTime = wavegenobj.BitDuration;          % Generate waveform in the step size corresponding to bit duration

Calculate Doppler shift and latency for a given satellite scenario.

% Initialize satellite scenario
sc = satelliteScenario;
% Set up the satellites based on the RINEX data
sat = satellite(sc,almFileName,OrbitPropagator="gps");
rx = groundStation(sc,rxlla(1),rxlla(2),Altitude=rxlla(3)); % Set up the receiver which doesn't move
rx.MinElevationAngle = minElevationAngle;

sc.StartTime = startTime;
sc.StopTime = sc.StartTime + seconds(waveDuration-stepTime);
sc.SampleTime = stepTime;

% Calculate Doppler shift and latency over time for all the visible satellites
dopShifts = dopplershift(sat,rx,Frequency=centerFrequency).';
ltncy = latency(sat,rx).';

Initialize values that aid in the signal-to-noise ratio (SNR) calculation.

c = physconst("LightSpeed"); % Speed of light in m/sec
Pt = 44.8;                   % Typical transmission power of GPS satellite in watts
Dt = 12;                     % Directivity of the transmit antenna in dBi
DtLin = db2pow(Dt);
Dr = 4;                      % Directivity of the receive antenna in dBi
DrLin = db2pow(Dr);
k = physconst("boltzmann");  % Boltzmann constant in Joules/Kelvin
T = 300;                     % Room temperature in Kelvin

Calculate power at the receiver from the free space path-loss equation.

Pr   = Pt*DtLin*DrLin./ ...
    ((4*pi*(centerFrequency+dopShifts).*ltncy).^2);

Calculate the signal to noise ratio for each visible satellite. Add some signal power (here 3 dB) to account for losses when transmitting with an SDR.

snrs = 10*log10(Pr/(k*T*sampleRate)) + 3;

Generate Waveform and Add Impairments

Initialize the configuration file from the almanac.

satIndices = find(~isnan(ltncy(1,:)));
navcfg = HelperGPSAlmanac2Config(almFileName,navDataType,satIndices,startTime);
visiblesatPRN = [navcfg(:).PRNID]
visiblesatPRN = 1×8

    10    13    15    20    21    24    29    32

Generate the navigation data.

% Generate GPS navigation data
tempnavdata = HelperGPSNAVDataEncode(navcfg(1));
navdata = zeros(length(tempnavdata),length(navcfg));
navdata(:,1) = tempnavdata;
for isat = 2:length(navcfg)
    navdata(:,isat) = HelperGPSNAVDataEncode(navcfg(isat));
end

Configure the GPS waveform generation object.

wavegenobj.PRNID = visiblesatPRN
wavegenobj = 
  gpsWaveformGenerator with properties:

           SignalType: "legacy"
                PRNID: [10 13 15 20 21 24 29 32]
          EnablePCode: false
    HasDataWithCACode: true
           SampleRate: 5000000

  Show all properties

gnsschannelobj = HelperGNSSChannel(FrequencyOffset=dopShifts(1,satIndices), ...
    SignalDelay=ltncy(1,satIndices), ...
    SignalToNoiseRatio=snrs(1,satIndices), ...
    SampleRate=sampleRate,RandomStream="mt19937ar with seed",Seed=seed)
gnsschannelobj = 
  HelperGNSSChannel with properties:

               SampleRate: 5000000
    IntermediateFrequency: 0
       DisableImpairments: false
          FrequencyOffset: [956.0901 -3.2174e+03 -2.5058e+03 316.0502 1.7671e+03 1.7725e+03 -1.8776e+03 3.4268e+03]
              SignalDelay: [0.0767 0.0808 0.0715 0.0728 0.0744 0.0771 0.0691 0.0803]
       SignalToNoiseRatio: [-11.2812 -11.7307 -10.6680 -10.8213 -11.0074 -11.3176 -10.3708 -11.6799]
             RandomStream: "mt19937ar with seed"
                     Seed: 73

numsteps = round(waveDuration/stepTime);
samplesPerStep = sampleRate*stepTime;

Initialize the waveform. If you enable the impairments, number of channels in the waveform is set to 1 because all the satellite signals are combined to form a single stream. If you disable the impairments, number of channel is equal to the number of visible satellites.

numchannels = 1*enableImpairments + length(visiblesatPRN)*(~enableImpairments);
gpswaveform = zeros(numsteps*samplesPerStep,numchannels);

Optionally, initialize the object that writes the waveform to a file.

if WriteWaveToFile == true
    bbwriter = comm.BasebandFileWriter(waveformFileName,sampleRate,0);
end

Generate the waveform.

for istep = 1:numsteps
    idx = (istep-1)*samplesPerStep + (1:samplesPerStep);
    navbit = navdata(istep,:);
    tempWaveform = wavegenobj(navbit);
    if enableImpairments == true
        gpswaveform(idx,:) = gnsschannelobj(tempWaveform);
    else
        gpswaveform(idx,:) = tempWaveform;
    end
    if WriteWaveToFile == true
        bbwriter(gpswaveform(idx,:))
    end
    
    % Update the properties of the channel object based on the values
    % calculated from the satellite scenario
    gnsschannelobj.SignalToNoiseRatio = snrs(istep,satIndices);
    gnsschannelobj.FrequencyOffset = dopShifts(istep,satIndices);
    gnsschannelobj.SignalDelay = ltncy(istep,satIndices);
end

Visualize the spectrum of the waveform.

scope = spectrumAnalyzer(SampleRate=sampleRate,AveragingMethod="exponential",ForgettingFactor=1);
scope.SpectrumUnits = "dBW";
% Plot only 1 sec of the waveform spectrum.
wlen = sampleRate; % Number of samples corresponding to one second
if length(gpswaveform) > wlen
    scope(gpswaveform(end-wlen+1:end))
else
    % If the length of the generated waveform is less than one second,
    % visualize the spectrum of the entire waveform
    scope(gpswaveform)
end

Set Up Radio

Call the radioConfigurations (Wireless Testbench) function. The function returns all available radio setup configurations that you saved using the Radio Setup (Wireless Testbench) wizard.

if useSDR == 1
    savedRadioConfigurations = radioConfigurations;

To update the drop-down menu with your saved radio setup configuration names, click Update. Then select the radio to use with this example.

    savedRadioConfigurationNames = [string({savedRadioConfigurations.Name})];
    if ~isempty(savedRadioConfigurationNames)
        radio = savedRadioConfigurationNames(1) ;
    end
end

Transmit Waveform over SDR

Once you connect an SDR, broadcast the GPS signal over-the-air.

if useSDR == 1 & ~isempty(savedRadioConfigurationNames) % Using SDR
    if ~exist("txradio","var")
        txradio = basebandTransmitter(radio);
        txradio.RadioGain = 10;
        txradio.CenterFrequency = centerFrequency;
        txradio.SampleRate = sampleRate
    end
    transmit(txradio,gpswaveform,"once")
end

Further Exploration

This example shows transmission of the signal using basebandTransmitter (Wireless Testbench) object. Alternatively, you can use comm.SDRuTransmitter object, which supports more USRP platforms.

You can transmit the waveform generated in this example over-the-air using an SDR. Then, try to receive that waveform using another SDR, and perform the GPS receiver algorithms on the captured signal.

For a demonstration of how to use the signal waveform directly to evaluate receiver performance without physical hardware connections, see

Supporting Files

This example uses these data and helper files.

See Also

| |

Topics