Documentation Center

  • Trial Software
  • Product Updates

FRS/GMRS Walkie-Talkie Receiver with SDR Hardware

This example shows how to model a walkie-talkie receiver using a Software Defined Radio hardware device. The specific radio standard that this example follows is FRS/GMRS (Family Radio Service / General Mobile Radio Service) with CTCSS (Continuous Tone-Coded Squelch System). You can transmit a signal to the implemented receiver using a commercial walkie-talkie device.

In order to run this example, you need an SDR board with an appropriate receiver daughterboard that supports the UHF 462-467 MHz band (for example, ADI FMCOMMS1). Please refer to the SDR docthe SDR doc to learn how to download the FPGA bitstream and configure your host computer to work with an SDR System object such as the comm.SDRADIFMCOMMSReceiver.

This example is designed to work with USA standards for FRS/GMRS operation. The technical specifications for these standards can be found at [ 1 ] and [ 2 ]. Operation in other countries may or may not work.


Walkie-talkies provide a subscription-free method of communicating over short distances. Although their popularity has been diminished by the rise of cell phones, walkie-talkies are still useful when lack of reception or high per-minute charges hinders cell phone use.

Modern walkie-talkies operate on the FRS/GMRS standards. Both standards use frequency modulation (FM) at 462 or 467 MHz, which is in the UHF (Ultra High Frequency) band. The SDR RF device in this example will receive messages at either 462 or 467 MHz, in a manner that is compatible with FRS/GMRS devices.

Please refer to the Simulink® model in the FRS/GMRS Walkie-Talkie Receiver with SDR Hardware example for a block diagram view of the system.


The getParamsSdrfFRSGMRSRxDemo.mgetParamsSdrfFRSGMRSRxDemo.m script initializes some simulation parameters and generates a structure, frsRx. The fields of this structure are the parameters of the FRS/GMRS receiver system at hand. You can change the input arguments in a local copy of this file in order to match your hardware.

Type 'help sdrload' to see all possible board names.

frsRx = getParamsSdrfFRSGMRSRxDemo ( ...
    'MotherboardName',   'Xilinx ML605', ...
    'RFBoardName',       'ADI FMCOMMS1 RevB', ...
    'Channel',           12, ...
    'Code',              5, ...
    'DecodeThreshold',   0.10 ...

Load FGPA Image

The example communicates with the SDR board using the SDR receiver System object. An image must be loaded onto the FPGA. One can use sdrload to download to the FPGA via a JTAG cable or one can copy the FPGA SystemACE images to the compact flash to initialize the FPGA via SystemACE. See sdrloadsdrload and sdrfgensysacesdrfgensysace. One can uncomment these lines to use sdrload for this example:

sdrload('Device',  frsRx.MotherboardName, ...
        'RFBoard', frsRx.RFBoardName);

FRS/GMRS Receiver

The FRS/GMRS receiver example tunes the SDR board to receive at the center frequency specified by the channel selection. The script applies automatic gain control (AGC) and FM demodulates the received signal. A CTCSS tone decoder passes the demodulated signal to an audio device if the received code matches the selected code.

AGC and Channel Selectivity Filter

Automatic gain controller applies a variable gain to the received signal to assure that the received signal amplitude is at a known level. The desired amplitude is set to 1. The AGC updates the gain periodically. The update period is set to 200. In this example, the walkie-talkie transmitter is likely nearby the SDR board, which implies that the received signal should not suffer from fading, and the received signal-to-noise ratio (SNR) should be high. In practice, the received signals will likely suffer from fading and low SNR.

This script uses a low pass channel separation filter to reduce the signals from an adjacent channel. The gap between adjacent channels is 25 kHz, which means the baseband bandwidth is at most 12.5 kHz. Thus, we choose the cutoff frequency to be 10 kHz. Create a digital filter System object that implements an FIR transfer function and set the Numerator property to the value specified in the frsRx structure.

hChanFilt = dsp.FIRFilter('Numerator', frsRx.ChannelFilterNumerator)

Next, a channel selector computes the average power of the filtered signal. If it is greater than a threshold (set to a default of 10%), the channel selector determines that the received signal is from the correct channel and it allows the signal to pass through. In the case of an out-of-band signal, although the channel separation filter reduces its magnitude, it is still FM modulated and the modulating signal will be present after FM demodulation. To reject such a signal completely, the channel selector outputs zero.

FM Demodulation and Decimation

This example implements FM demodulation by taking the phase difference of consecutive complex samples. Use a delay System object to delay the received baseband signal to prepare for the phase difference calculation.

hDelay = dsp.Delay

A decimation filter converts the sampling rate to 8 kHz. This rate is one of the native sampling rates of your host computer's output audio device. Use an FIR decimator System object to convert the 200 kHz signal to an 8 kHz signal. Set the decimation factor to 25, and the numerator to the value specified in the frsRx structure.

hDecimator = dsp.FIRDecimator(frsRx.ToAudioDecimationFactor, ...

Continuous Tone-Coded Squelch System (CTCSS)

The CTCSS [ 3 ] decoder computes the power at each CTCSS tone frequency using the Goertzel algorithm [ 4 ] and outputs the code with the largest power. The Goertzel algorithm provides an efficient method to compute the frequency components at predetermined frequencies, i.e., the tone code frequencies used by FRS/GMRS.

The script compares the estimated received code with the preselected code and then sends the signal to the audio device if the two codes match. When the preselected code is zero, it indicates no squelch system is used and the decision block passes the signal at the channel to the audio device no matter which code is used.

Audio Output

A high pass filter with a cutoff frequency of 260 Hz filters out the CTCSS tones, which have a maximum frequency of 250 Hz. Use an audio player System object to play the received signals through your computer's speakers. If you do not hear any sound, please select another device using the DeviceName property of the audio player object, hAudio.

hAudioFilt = dsp.FIRFilter('Numerator', frsRx.AudioFilterNumerator)

hAudio = dsp.AudioPlayer(frsRx.AudioSampleRate)

Construct the SDR System Object

You set the properties of the SDR System object using name-value pair arguments.

You can supply the IP address of the SDR board as an argument when you construct the object. The default IP addresses using the FPGA bitstreams supplied with the product are '' for an ADI radio and '' for an Epiq radio. Your host network adapter must be on the same subnetwork as the radio.

Other parameters are set in the frsRx structure to reasonable values for this example. A radio ADC rate and radio decimation factor are chosen to acheive an incoming sample rate of roughly 200KHz. The frame length is chosen to allow for a further decimation to an audio sample rate of 8KHz using an integer decimation factor.

The center frequency source is set to an input port. Select the output data type as single to reduce the required memory and speed up execution.

paramValuePairs = { ...
    'CenterFrequencySource',    'Input port', ...
    'Gain',                     frsRx.RadioGain, ...
    'ADCRate',                  frsRx.RadioADCRate, ...
    'DecimationFactor',         frsRx.RadioDecimationFactor, ...
    'FrameLength',              frsRx.RadioFrameLength, ...
    'DecimatorSelect',          'DDC decimator', ...
    'OutputDataType',           'single', ...
    'LostSamplesOutputPort',    true ...

switch (frsRx.RFBoardName)
    case 'ADI FMCOMMS1 RevB'
        hSDR = comm.SDRADIFMCOMMSReceiver( ...
            'IPAddress', '', ...
    case {'Epiq Bitshark RevB','Epiq Bitshark RevC'}
        hSDR = comm.SDREpiqBitsharkReceiver( ...
            'IPAddress', '', ...

Running the Example

Turn on your walkie-talkie, set the channel to 12 and the private code to 5. The center frequency is a function of the selected channel number.

% Get the carrier frequency for the selected channel

fc = mConvertChan2FreqFRSGMRSDemo(frsRx.Channel)

Stream Processing Loop

Capture FRS/GMRS signals and demodulate for 20 seconds, which is specified by frsRx.StopTime. The SDR object returns a column vector, x. Because the MATLAB script may run faster than the hardware, the object also returns the actual size of the valid data in x using the second output argument, len. If len is zero, then there is no new data for the demodulator code to process.

  % Loop until the example reaches the target stop time.
  timeCounter = 0;
  while timeCounter < frsRx.StopTime

    [data, len, lostSamps] = step(hSDR, fc);

    if (lostSamps > 0)
        warning(['### ' num2str(lostSamps) ' samples from the radio have been lost.']);

    if len > 0

      % AGC and channel selectivity
      outAGC        = mAGC(data);
      outChanFilt   = step(hChanFilt, outAGC);
      x             = mChannelSelector(outChanFilt, frsRx.DecodeThreshold);

      % FM demodulator and decimation
      xDelay        = step(hDelay, x);
      y             = angle(xDelay .* conj(x));
      outRC         = step(hDecimator, y);

      % CTCSS decoder
      rcvdCode      = mCTCSSDecode(outRC, frsRx.ToneFrequencies, ...
                                   frsRx.GoertzelCoefficients, ...
      rcvdSig       = mDecision(outRC, rcvdCode, frsRx.Code);

      % Output to audio device
      audioSig      = step(hAudioFilt, rcvdSig);

      step(hAudio, audioSig);

      timeCounter = timeCounter + frsRx.RadioFrameTime;
catch ME

Release the audio and SDR resources.

clear hSDR


In this example, you used Communications System Toolbox™ System objects to build an FRS/GMRS receiver utilizing the SDR device. The example showed that the MATLAB script can process signals captured by the SDR device in real time.

Further Exploration

The CTCSS decoding computes the DFT (Discrete-Time Fourier Transform) of the incoming signal using the Goertzel algorithm and computes the power at the tone frequencies. Since the tone frequencies are very close to each other (only 3-4 Hz apart) the block length of the DFT should be large enough to provide enough resolution for the frequency analysis. However, long block lengths cause decoding delay. For example, a block length of 16000 will cause 2 seconds of delay because the CTCSS decoder operates at an 8 kHz sampling rate. This creates a trade-off between detection performance and processing latency. The optimal block length may depend on the quality of the transmitter and receiver, the distance between the transmitter and receiver, and other factors. You are encouraged to change the block length in the initialization function by navigating to the getParamsSdrfFRSGMRSRxDemo function and changing the value of the CTCSSDecodeBlockLength field. This will enable you to observe the trade-off and find the optimal value for your transmitter/receiver pair.


The following scripts are used in this example.


Was this topic helpful?