Main Content

Family Radio Service (FRS) Full-Duplex Transceiver with USRP™ Hardware

This example shows how to use two Universal Software Radio Peripheral devices exploiting SDRu (Software Defined Radio USRP System objects to perform full duplex communication by transmitting/receiving recorded audio simultaneously using MATLAB® and the FRS protocol.

Please refer to the Setup and Configuration section ofGuided USRP Radio Support Package Hardware Setup for details on configuring your host computer to work with the SDRu Transmitter and SDRu Receiver System objects™.

In order to run this example, you need two host computers connected to two USRP radios with daughterboards (e.g. SBX or WBX) that support full-duplex operation and the FRS band. Using this script, FRSFullDuplexTransceiverWithUSRPHardwareExample, the first USRP radio sends one audio signal at 467.6125 MHz, and simultaneously receives another audio signal at 467.6625 MHz. The second USRP radio sends at 467.6625 MHz and receives at 467.6125 MHz using the MATLAB script FRSFullDuplexTransceiverWithUSRPHardwareExample_2. Each host computer plays the received audio signal on its audio device.

Discover Radio

Discover radio(s) connected to your computer. This example uses the first USRP radio found using the findsdru function. Check if the radio is available and record the radio type. If no available radios are found, the example uses a default configuration for the system but does not run the main loop.

connectedRadios = findsdru;
Checking radio connections...
if strncmp(connectedRadios(1).Status, 'Success', 7)
  radioFound = true;
  platform = connectedRadios(1).Platform;
  switch connectedRadios(1).Platform
    case {'B200','B210'}
      address = connectedRadios(1).SerialNum;
    case {'N200/N210/USRP2','X300','X310','N300','N310','N320/N321'}
      address = connectedRadios(1).IPAddress;
  end
else
  radioFound = false;
  address = '192.168.10.2';
  platform = 'N200/N210/USRP2';
end

Initialization

The configureFDTx and configureFDRx MATLAB functions initialize simulation parameters and generate parameter structures for the FRS transmitter and receiver systems.

The frequency calibration compensation value, rfRxFreqCorrection, can be determined for your USRP environment by running the MATLAB script FrequencyOffsetCalibrationReceiverUSRPHardwareExample while sending a sine wave at the RF receiver center frequency, rfRxFreq, with MATLAB script FrequencyOffsetCalibrationTransmitterUSRPHardwareExample.

% Transmitter Initialization
rfTxFreq = 467.6125e6; % RF Transmitter Center Frequency (Hz)
frsFDTxParams = configureFDTx(platform, rfTxFreq);

% Receiver Initialization
rfRxFreq = 467.6625e6; % RF Receiver Center Frequency (Hz)
rfRxFreqCorrection = -4e3; % Frequency calibration compensation value (Hz)
rfRxFreqActual = rfRxFreq + rfRxFreqCorrection;
frsFDRxParams = configureFDRx(platform, rfRxFreqActual);

Transmit One Audio File Using FRS Waveform

This example uses a source object to generate data signals for the transmitter. The source signal is a multimedia audio file. When using a multimedia file, the sampling rate needs to be converted to 8 kHz; therefore, the FRSGMRSDemoAudioSource object employs a rate conversion filter to convert the 22.5 kHz signal to an 8 kHz signal.

% Create a data source to transmit the contents of a sound file at a
% sampling frequency of 8 kHz.
source = FRSGMRSDemoSource('Sound file', frsFDTxParams.SourceSampleRate);
source.AudioFileName = 'speech_dft.avi';

% The Continuous Tone-Coded Squelch System (CTCSS) filters out
% undesired communication or interference from these other users by
% generating a tone between 67 Hz and 250 Hz and transmitting it along with
% the source signal.
ctcss = dsp.SineWave(frsFDTxParams.CTCSSAmplitude, ...
    frsFDTxParams.CTCSSToneFrequencies(frsFDTxParams.CTCSSCode), ...
    'SampleRate', frsFDTxParams.SourceSampleRate, ...
    'SamplesPerFrame', frsFDTxParams.SourceFrameLength, ...
    'OutputDataType', 'single');
                  
% The interpolator and FM modulator convert the sampling rate of the sum of
% the modulating signal and the CTCSS tone to match the USRP hardware
% sampling rate of 200 kHz.
interpolator = dsp.FIRInterpolator(frsFDTxParams.InterpolationFactor, ...
    frsFDTxParams.InterpolationNumerator);
     
fmMod = comm.FMModulator('SampleRate', frsFDTxParams.RadioSampleRate, ...
    'FrequencyDeviation', frsFDTxParams.FrequencyDeviation);

% The SDRu transmitter sets the interpolation factor and master clock rate
% so that the example uses round numbers to convert the sampling rate from
% 8 kHz to 200 kHz. B200 and B210 series USRP radios are addressed using
% a serial number while USRP2, N200, N210, X300 and X310 radios are
% addressed using an IP address.

% Set up transmitter radio object to use the found radio
switch platform
  case {'B200','B210'}
    radioTx = comm.SDRuTransmitter('Platform', platform, ...
        'SerialNum', address, ...
        'MasterClockRate', frsFDTxParams.RadioMasterClockRate, ...
        'CenterFrequency', frsFDTxParams.CenterFrequency,...
        'Gain', frsFDTxParams.RadioGain, ...
        'InterpolationFactor', frsFDTxParams.RadioInterpolationFactor)
  case {'X300','X310','N300','N310','N320/N321'}
    radioTx = comm.SDRuTransmitter('Platform', platform, ...
        'IPAddress', address, ...
        'MasterClockRate', frsFDTxParams.RadioMasterClockRate, ...
        'CenterFrequency', frsFDTxParams.CenterFrequency,...
        'Gain', frsFDTxParams.RadioGain, ...
        'InterpolationFactor', frsFDTxParams.RadioInterpolationFactor)
  case {'N200/N210/USRP2'}
    radioTx = comm.SDRuTransmitter('Platform', platform, ...
        'IPAddress', address, ...
        'CenterFrequency', frsFDTxParams.CenterFrequency,...
        'Gain', frsFDTxParams.RadioGain, ...
        'InterpolationFactor', frsFDTxParams.RadioInterpolationFactor)
end
radioTx = 
  comm.SDRuTransmitter with properties:

                 Platform: 'B200'
                SerialNum: '30EA06C'
           ChannelMapping: 1
          CenterFrequency: 467612500
    LocalOscillatorOffset: 0
                     Gain: 15
                PPSSource: 'Internal'
              ClockSource: 'Internal'
          MasterClockRate: 20000000
      InterpolationFactor: 100
        TransportDataType: 'int16'
          EnableBurstMode: false

Receive Another Audio File Using FRS Demodulation

Create objects to resample the input to 200 kHz, perform automatic gain control, perform channel selectivity filtering, FM demodulate, resample to an 8 kHz audio output, perform CTCSS decoding, filter out the CTCSS tones, then send the signal to an audio output device.

% Set up transmitter radio object to use the found radio
switch platform
  case {'B200','B210'}
    radioRx = comm.SDRuReceiver('Platform', platform, ...
        'SerialNum', address, ...
        'MasterClockRate', frsFDRxParams.RadioMasterClockRate, ...
        'CenterFrequency', frsFDRxParams.CenterFrequency,...
        'Gain', frsFDRxParams.RadioGain, ...
        'DecimationFactor', frsFDRxParams.RadioDecimationFactor, ...
        'SamplesPerFrame', frsFDRxParams.RadioFrameLength, ...
        'OutputDataType', 'single')
  case {'X300','X310','N300','N310','N320/N321'}
    radioRx = comm.SDRuReceiver('Platform', platform, ...
        'IPAddress', address, ...
        'MasterClockRate', frsFDRxParams.RadioMasterClockRate, ...
        'CenterFrequency', frsFDRxParams.CenterFrequency,...
        'Gain', frsFDRxParams.RadioGain, ...
        'DecimationFactor', frsFDRxParams.RadioDecimationFactor, ...
        'SamplesPerFrame', frsFDRxParams.RadioFrameLength, ...
        'OutputDataType', 'single')
  case {'N200/N210/USRP2'}
    radioRx = comm.SDRuReceiver('Platform', platform, ...
        'IPAddress', address, ...
        'CenterFrequency', frsFDRxParams.CenterFrequency,...
        'Gain', frsFDRxParams.RadioGain, ...
        'DecimationFactor', frsFDRxParams.RadioDecimationFactor, ...
        'SamplesPerFrame', frsFDRxParams.RadioFrameLength, ...
        'OutputDataType', 'single')
end
radioRx = 
  comm.SDRuReceiver with properties:

                 Platform: 'B200'
                SerialNum: '30EA06C'
           ChannelMapping: 1
          CenterFrequency: 467658500
    LocalOscillatorOffset: 0
                     Gain: 5
                PPSSource: 'Internal'
              ClockSource: 'Internal'
          MasterClockRate: 20000000
         DecimationFactor: 100
        TransportDataType: 'int16'
           OutputDataType: 'single'
          SamplesPerFrame: 4000
          EnableBurstMode: false

% AGC
agc = comm.AGC;

% Low pass filter for channel separation
channelFilter = frsFDRxParams.ChannelFilter;
                          
% FM demodulator 
fmDemod = comm.FMDemodulator('SampleRate', frsFDRxParams.RadioSampleRate, ...
    'FrequencyDeviation', frsFDRxParams.FrequencyDeviation);

% Decimation filter to resample to 8 kHz
decimator = dsp.FIRDecimator(frsFDRxParams.DecimationFactor, ...
    frsFDRxParams.DecimationNumerator);

% The CTCSS decoder compares the estimated received code with the
% preselected code and then sends the signal to the audio device if the two
% codes match.
decoder = FRSGMRSDemoCTCSSDecoder(...
    'MinimumBlockLength', frsFDRxParams.CTCSSDecodeBlockLength, ...
    'SampleRate', frsFDRxParams.AudioSampleRate);

% High pass filter to filter out CTCSS tones
audioFilter = frsFDRxParams.AudioFilter;

% Audio device writer
audioPlayer = audioDeviceWriter(frsFDRxParams.AudioSampleRate);

Stream Processing Loop

% Perform stream processing if a radio is found.
if radioFound
    % Loop until the example reaches the target stop time.
    timeCounter = 0;
    
    while timeCounter < frsFDTxParams.StopTime
        % Transmitter stream processing
        % -----------------------------------------------------------------
        dataTx = step(source);  % Generate audio waveform 
        dataWTone = dataTx + step(ctcss);  % Add CTCSS tones

        % Interpolation FM modulation
        outResamp = step(interpolator, dataWTone);  % Resample to 200 kHz
        outMod = step(fmMod, outResamp);
        step(radioTx, outMod); % Transmit to USRP radio
        
        % Receiver stream processing
        % -----------------------------------------------------------------
        dataRx = step(radioRx);
        outAGC = step(agc, dataRx); % AGC
        outChanFilt = step(channelFilter, outAGC); % Adjacent channel filtering
        rxAmp = mean(abs(outChanFilt));
        if rxAmp > frsFDRxParams.DetectionThreshold
            outThreshold = outChanFilt;
        else
            outThreshold = complex(single(zeros(frsFDRxParams.RadioFrameLength, 1)));
        end

        % FM demodulation and decimation
        outFMDemod = step(fmDemod, outThreshold); % FM demodulate
        outDecim  = step(decimator, outFMDemod); % Resample to 8 kHz

        % CTCSS decode and conditionally send to audio output
        rcvdCode = step(decoder, outDecim);
        if (rcvdCode == frsFDRxParams.CTCSSCode) || (frsFDRxParams.CTCSSCode == 0)
            rcvdSig = outDecim;
        else
            rcvdSig = single(zeros(frsFDRxParams.AudioFrameLength, 1));
        end

        audioSig = step(audioFilter, rcvdSig); % Filter out CTCSS tones
        step(audioPlayer, audioSig); % Audio output
        timeCounter = timeCounter + frsFDRxParams.RadioFrameTime;

    end
else
    warning(message('sdru:sysobjdemos:MainLoop'))
end

% Release all SDRu and audio resources , FM Modulator and Demodulator
release(fmMod)
release(radioTx)
release(fmDemod)
release(radioRx)
release(audioPlayer)

Conclusion

In this example, you used Communications Toolbox™ System objects to perform full duplex transmission and reception using FRS waveforms and two USRP radios.

Appendix

The following functions are used in this example.